1 / 58

윈도우 커널모드 드라이버 64 비트 포팅

윈도우 커널모드 드라이버 64 비트 포팅. 월간 마이크로소프트웨어 2005.9 김성현 2006.1.21. 목차. 64 비트 세상 제품 포팅 계획 64 비트 CPU 64 비트 드라이버 빌드 DDK 예제 포팅 포팅 문제 해결. 64 비트 세상. INTEL P4 프레스캇 630 – 3GHz System Bus : 800MHz L1 Cache : 16KB L2 Cache : 2MB 64Bit 지원 ( EM64T ) 하이퍼스레딩 기술 지원. 64 비트 드라이버 포팅 ! Why?.

ghada
Télécharger la présentation

윈도우 커널모드 드라이버 64 비트 포팅

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 윈도우 커널모드 드라이버 64비트 포팅 월간 마이크로소프트웨어 2005.9 김성현 2006.1.21

  2. 목차 • 64비트 세상 • 제품 포팅 계획 • 64비트 CPU • 64비트 드라이버 빌드 • DDK 예제 포팅 • 포팅 문제 해결

  3. 64비트 세상 • INTEL P4 프레스캇 630 – 3GHz • System Bus : 800MHz • L1 Cache : 16KB • L2 Cache : 2MB • 64Bit 지원( EM64T ) • 하이퍼스레딩 기술 지원

  4. 64비트 드라이버 포팅! Why? • 64비트 윈도우 정책 • 32비트 APP 지원, 32비트 Driver 지원안함 • WOW64 • 32비트 APP 에뮬레이션 레이어 • 32비트 APP 바이너리 그대로 수행 • 32비트 Driver 동작 못함 • 64비트 드라이버 바이너리 필요!!! • 32비트, 64비트 One Source, Two Binary

  5. NT Executive Win32k.sys Kernel Mode User Mode Reserved Address Space 0x00000000`7FFEFFFF or 0x00000000`FFFEFFFF 64-bit ntdll.dll WoW64.dll WoW64win.dll WoW64cpu.dll 32-bit ntdll.dll 32-bit modules

  6. 제품 포팅 계획 32비트 APP 64비트 APP 유저모드 커널모드 64비트 Driver 64비트 Driver 방법1 (제약사항있음) 방법2

  7. FileSystem Redirection • 32비트 프로세스로 제품설치시 주의 • 32비트 APP 접근시 WOW64에서 처리 • C:\Program Files => C:\Program Files(x86) • C:\windows\system32 => C:\windows\syswow64 • Wow64DisableWow64FsRedirection() API 로 제어가능

  8. Registry Redirection • 32비트 APP 접근시 WOW64에서 처리 • HKLM\Software => HKLM\Software\Wow6432Node • HKCR => HKCR\Wow6432Node • RegOpenKeyEx(), RegCreateKeyEx() • KEY_WOW64_64KEY: 64bit Registry 접근 • KEY_WOW64_32KEY: 32bit Registry 접근

  9. 64비트 CPU 종류 • AMD64 ( AMD ) • 32비트 호환 • Athlon64, Opteron • IA64 ( INTEL ) • 진보적인 아키텍쳐(RISC 기반, 32비트 호환?) • Itanium, Itanium2 • EM64T ( INTEL ) • AMD64 Clone? 개발시 AMD64로 취급 • ZEON EM64T, Pentium4 with EM64T • Q) Dual P4 Hiper Threading EM64T

  10. CPU별 바이너리 종류

  11. 64비트 드라이버 빌드 DDK • 64비트 빌드환경을 제공하는 DDK • Windows Server 2003 SP1 DDK • http://www.microsoft.com/whdc/devtools/ddk/default.mspx CD 신청 • http://www.microsoft.com/whdc/driver/wdf/KMDF_pkg.mspx Download 가능 • Thanks OSR!!!

  12. 64비트 드라이버 빌드 • 32비트 드라이버 • NT4 빌드? 2K 빌드? XP 빌드? • 64비트 드라이버 • 2K3 빌드! ( XP x64 Edition 커널 )

  13. 64비트 드라이버 빌드 IA64 define : _M_IA64, __IA64__ ; x64 define : _M_AMD64, __AMD64__

  14. 64비트 Windows • Windows XP x64 Edition • Windows XP 64bit Edition • Windows Server 2003 x64 Edition • Windows Server 2003 for Itanium based system

  15. 인라인 어셈블리 • OH NO!!! • X86 instruction • AMD64 instruction • IA64 instruction • 64비트 컴파일러는 인라인 어셈블리 미지원 • 원칙 : 1 C-Source Code, 3 Binary

  16. AMD64 Instruction • mov [rbp-0x80],rcx • mov rdi,[rdi+0x18] • movzx ecx,byte ptr [rax+rdi] • sub rsp,rcx • and rsp,0xfffffffffffffff0 • mov rdi,rsp • mov rsi,[rbp+0x100] • add rsi,0x28 • test byte ptr [rbp+0xf0],0x1

  17. IA64 Instruction • addl r2=ffffffff`ffe020b8, gp ;; • ld8 r2=[r2] • nop.i 0 ;; • ld8 r3=[r2], 8 ;; • ld8 gp=[r2] • mov b6=r3, +0 • nop.m 0 • nop.i 0 • br.cond.sptk.few b6

  18. 64비트 포팅 가이드라인 • _WIN64 define ( _WIN32 ) • __AMD64__, __IA64__ • 포인터 사용 체크 • sizeof(PULONG) != sizeof(ULONG) • 포인터 연산 체크 • 32비트 + 32비트 = 64비트 • 0xFFFFFFFF != -1

  19. 64비트 포팅 가이드라인 • ~((UINT64)(PAGE_SIZE-1))==(UINT64)~(PAGE_SIZE-1)PAGE_SIZE=0x1000UL//UnsignedLong-32bitsPAGE_SIZE-1=0x00000fff • LHS expression: • //Unsignedexpansion(UINT64)(PAGE_SIZE-1)=0x0000000000000fff~((UINT64)(PAGE_SIZE-1))=0xfffffffffffff000 • RHS expression: • ~(PAGE_SIZE-1)=0xfffff000(UINT64)(~(PAGE_SIZE-1))=0x00000000fffff000 • ~((UINT64)(PAGE_SIZE-1))!=(UINT64)(~(PAGE_SIZE-1))

  20. 드라이버 포팅 예제 • NT4 DDK 샘플 • DDK\src\general\portio • 64비트 빌드환경 • Windows Server 2003 Checked IA-64(또는 x64) 실행 • 일반샘플처럼 빌드 • 생성된 Buildchk_wnet_IA64(또는 AMD64).err 확인

  21. 드라이버 포팅 예제

  22. 오류내용 • 1>sys\genport.c(223) : error C4312: 'type cast' : conversion from 'ULONG' to 'PVOID' of greater size • 1>sys\genport.c(513) : error C4311: 'type cast' : pointer truncation from 'PVOID' to 'ULONG' • 1>sys\genport.c(526) : error C4311: 'type cast' : pointer truncation from 'PVOID' to 'ULONG' • 1>sys\genport.c(526) : error C4312: 'type cast' : conversion from 'unsigned long' to 'PUCHAR' of greater size • 1>sys\genport.c(530) : error C4311: 'type cast' : pointer truncation from 'PVOID' to 'ULONG' • 1>sys\genport.c(530) : error C4312: 'type cast' : conversion from 'unsigned long' to 'PUSHORT' of greater size • 1>sys\genport.c(534) : error C4311: 'type cast' : pointer truncation from 'PVOID' to 'ULONG'

  23. 포인터의 타입캐스팅 • 데이터 타입의 크기에 대한 문제 • 32비트 환경 포인터 크기: 32비트 • 32비트 환경 ULONG 크기: 32비트 • 64비트 환경 포인터 크기: 64비트 • 64비트 환경 ULONG 크기: 32비트 • 포인터와 ULONG을 구분하지 않고 작성된 코드에 대한 문제

  24. 포인터의 타입캐스팅 • 1>sys\genport.c(513) : error C4311: 'type cast' : pointer truncation from 'PVOID' to 'ULONG‘ • 511 : if (nPort >= pLDI->PortCount || • 512 : (nPort + DataBufferSize) > pLDI->PortCount || • 513 : (((ULONG)pLDI->PortBase + nPort) & • (DataBufferSize - 1)) != 0) • pLDI->PortBase는 PVOID, nPort 는 ULONG • 타입캐스팅이 에러?

  25. 포인터의 타입캐스팅 • 해결방법 1 • 513 : (((ULONG_PTR)pLDI->PortBase + nPort) & • (DataBufferSize - 1)) != 0) • ULONG_PTR • ULONG 형 포인터? X • 32비트 빌드시: 32비트 크기의 정수형 • 64비트 빌드시: 64비트 크기의 정수형

  26. 포인터의 타입캐스팅 • 해결방법 2 • 513 : ((PtrToUlong(pLDI->PortBase) + nPort) & • (DataBufferSize - 1)) != 0) • PtrToUlong() 매크로 • #define PtrToUlong( p ) ((ULONG)(ULONG_PTR) (p) ) • 주의) pLDI->PortBase가 32비트로 잘림

  27. 포인터의 타입캐스팅 • 1>sys\genport.c(526) : error C4311: 'type cast' : pointer truncation from 'PVOID' to 'ULONG' • 1>sys\genport.c(526) : error C4312: 'type cast' : conversion from 'unsigned long' to 'PUCHAR' of greater size • 524 : case IOCTL_GPD_READ_PORT_UCHAR: • 525: *(PUCHAR)pIOBuffer = READ_PORT_UCHAR( • 526: (PUCHAR)((ULONG)pLDI->PortBase + nPort) ); • 527: break; • 한줄에 2가지 오류

  28. 포인터의 타입캐스팅 • 방법 1 • (PUCHAR)((ULONG_PTR)pLDI->PortBase + nPort)); • 방법 2 • (PUCHAR)PtrToUlong(pLDI->PortBase) + nPort); • 방법 2+ • (PUCHAR)UlongToPtr(PtrToUlong(pLDI->PortBase) + nPort)); • 신중히 결정할 것 • 주의) 반복되는 오류처리

  29. 타입캐스팅을 넘어서 • 1>sys\genport.c(223) : error C4312: 'type cast' : conversion from 'ULONG' to 'PVOID' of greater size • 223 : pLocalInfo->PortBase = • (PVOID)MappedAddress.LowPart; • MappedAddress.LowPart 는 ULONG • 타입캐스팅으로 해결? 아니면?

  30. 타입캐스팅을 넘어서 • 해결방법 1 • 223 : pLocalInfo->PortBase = UlongToPtr( MappedAddress.LowPart ); • 해결방법 2 • 223 : pLocalInfo->PortBase = (PVOID)(ULONG_PTR)MappedAddress.LowPart;

  31. 타입캐스팅을 넘어서 • 해결방법 3 • 데이터구조를 생각하자 • LowPart? HighPart? • MappedAddress의 타입 • PHYSICAL_ADDRESS MappedAddress; • typedef LARGE_INTEGER PHYSICAL_ADDRESS, *PPHYSICAL_ADDRESS;

  32. 타입캐스팅을 넘어서 • typedef union _LARGE_INTEGER { • struct { • ULONG LowPart; • LONG HighPart; • }; • struct { • ULONG LowPart; • LONG HighPart; • } u; • LONGLONG QuadPart; // 64비트!!! • } LARGE_INTEGER;

  33. 타입캐스팅을 넘어서 • 해결방법 3 • 223 : pLocalInfo->PortBase = (PVOID)MappedAddress.QuadPart; • 198: HalTranslateBusAddress( Isa, • 199: 0, • 200: PortAddress, • 201: &MemType, • 202: &MappedAddress );

  34. 응용 프로그램과 드라이버가 공유하는 구조체 • 기존 32비트 응용프로그램이 사용하던 구조체를 새로 작성되는 64비트 드라이버에 전달해야 할 때 • 32비트 환경과 64비트 환경에서 데이터 크기가 달라지는 타입에 대한 문제

  35. 응용 프로그램과 드라이버가 공유하는 구조체 • 응용 프로그램 코드 예제 • GENPORT_WRITE_INPUT InputBuffer • sscanf(argv[2],"%x",&InputBuffer.PortNumber); • InputBuffer.LongData = (ULONG)DataValue; • 드라이버 코드 예제 • GENPORT_WRITE_INPUT *pInputBuffer • nPortNum = pInputBuffer->PortNumber; • nLongData = pInputBuffer->LongData;

  36. 응용 프로그램과 드라이버가 공유하는 구조체 • Gpioctl.h • typedef struct _GENPORT_WRITE_INPUT { • ULONG PortNumber; // Port # to write to • union { // Data to be output to port • ULONG LongData; • USHORT ShortData; • UCHAR CharData; • }; • } GENPORT_WRITE_INPUT;

  37. 32 비트 gpdwrite.exe (ULONG 4 바이트, union 4 바이트) GENPORT_WRITE_INPUT 64 비트 genport.sys GENPORT_WRITE_INPUT (ULONG 4 바이트, union 4 바이트) 응용 프로그램과 드라이버가 공유하는 구조체 • 32비트 APP + 64비트 DRV

  38. 공유 구조체 문제 • 32비트, 64비트에서 크기가 다른 데이터가 존재하는 경우 • typedef struct _GENPORT_WRITE_INPUT { • PVOID PortNumber; • union { • ULONG LongData; • USHORT ShortData; • UCHAR CharData; • }; • } GENPORT_WRITE_INPUT;

  39. 32 비트 gpdwrite.exe (PVOID 4 바이트, union 4 바이트) GENPORT_WRITE_INPUT 64 비트 genport.sys GENPORT_WRITE_INPUT (PVOID 8 바이트, union 4 바이트) 공유 구조체 문제 • 32비트 APP + 64비트 DRV

  40. 공유 구조체 문제 해결 • 64비트 드라이버가 사용하는 32비트용 구조체 정의 • typedef struct _GENPORT_WRITE_INPUT_32 • { • ULONG PortNumber; • union { • ULONG LongData; • USHORT ShortData; • UCHAR CharData; • }; • } GENPORT_WRITE_INPUT;

  41. 32 비트 gpdwrite.exe (PVOID 4 바이트, union 4 바이트) GENPORT_WRITE_INPUT 64 비트 genport.sys GENPORT_WRITE_INPUT_32 (ULONG 4 바이트, union 4 바이트) 공유 구조체 문제 해결 • 32비트 APP + 64비트 DRV

  42. IoIs32bitProcess() • 시나리오 • 32비트 기존 응용프로그램 사용 • 64비트 드라이버 출시 후… • 64비트 응용프로그램 포팅 완료 • 64비트 드라이버의 운명은? • 32 APP, 64 APP 모두 지원 • 32 APP, 64 APP 구분 필요

  43. IoIs32bitProcess() • 64비트 APP + 64비트 DRV 64 비트 gpdwrite.exe (PVOID 8 바이트, union 4 바이트) GENPORT_WRITE_INPUT 64 비트 genport.sys GENPORT_WRITE_INPUT (PVOID 8 바이트, union 4 바이트)

  44. IoIs32bitProcess() • GENPORT_WRITE_INPUT *pInputBuffer • GENPORT_WRITE_INPUT_32 *pInputBuffer32 • If (IoIs32bitProcess( Irp ) == TRUE) • pInputBuffer32 = (GENPORT_WRITE_INPUT_32*) pIrp->AssociatedIrp.SystemBuffer; • else • pInputBuffer = (GENPORT_WRITE_INPUT*) pIrp->AssociatedIrp.SystemBuffer; • switch (IoctlCode) • { • case IOCTL_GPD_WRITE_PORT_ULONG: • If (IoIs32bitProcess( Irp ) == TRUE) • { • nPortNum = pInputBuffer32->PortNumber; • nLongData = pInputBuffer32->LongData; • } • Else // 64 bit • { • nPortNum = pInputBuffer->PortNumber; • nLongData = pInputBuffer->LongData; • }

  45. IoIs32bitProcess() • IOCTL Code 사용하는 방법 • 현재 • 64비트

  46. Quiz • #pragma pack(1) • typedef struct _PACK1_DATA • { • ULONG ul1; • UCHAR uc1; • } PACK1_DATA; • #pragma pack() • #pragma pack(8) • typedef struct _PACK8_DATA • { • UCHAR uc8; • PACK1_DATA p1d; • ULONG ul8; • } PACK8_DATA; • #pragma pack()

  47. Quiz • 32비트 환경에서 메모리 구성은? • 1 • 2 • 3 ul1 uc1 ul8 uc8 padding padding ul8 uc8 ul1 uc1 padding ul1 uc1 ul8 uc8 padding

  48. Data Misalignment 문제 • IA64에서 발생하는 문제 • 메모리 주소 경계에 맞지 않는 주소를 액세스할 경우 • APP => 비정상종료 • DRV => 블루스크린 • Bug Check 0x1E: KMODE_EXCEPTION_NOT_HANDLED • Parameter 1: 0x80000002 STATUS_DATATYPE_MISALIGNMENT

  49. Data Misalignment 문제 • #pragma pack(1) • typedef struct _GENPORT_WRITE_INPUT { • BOOLEAN bTest; • PVOID PortNumber; // Port # to write to • union { // Data to be output to port • ULONG LongData; • USHORT ShortData; • UCHAR CharData; • }; • } GENPORT_WRITE_INPUT; • #pragma pack()

  50. GENPORT_WRITE_INPUT 0 1 2 3 4 5 6 7 8 9 10 11 12 PortNumber LongData bTest Data Misalignment 문제 • 1바이트 정렬된 구조체의 메모리구조

More Related