'Device Driver'에 해당되는 글 2건

  1. 2013.11.09 Setting up Kernel mode debugging over a USB 2.0 Cable manually 1
  2. 2013.09.12 Device and Driver Layering I
2013. 11. 9. 00:57

Setting up Kernel mode debugging over a USB 2.0 Cable manually

  우리는 커널 혹은 디바이스 드라이버를 개발하거나 디버깅할 때, 주로 VMWare나 Virtual Box 등의 가상 머신 툴로 많이 작업을 합니다만, 아무래도 그런 가상 머신 환경은 리얼 PC 환경에 비해 한계성을 가질 수 밖에 없습니다. 이를 테면, 리얼 PC 환경과 가상 환경 간의 차이로 구현이 달라져야 하거나 최신 호스트 인터페이스 컨트롤러를 기반으로 동작해야 하는 디바이스 드라이버의 경우, 벤더에서 가상 머신 기반의 개발 및 디버깅 가능하도록 지원해주기 전까지는 그 어떠한 작업도 불가능할 수 밖에 없지요. 만약 호스트 컴퓨터 두 대가 있다면 이를 USB 케이블로 연결하여 한 대는 호스트로, 또다른 한 대는 타깃으로 설정하여 리얼 환경에서 디버깅을 가능하도록 할 것입니다. 그래서 오늘은 PC 두 대를 USB 2.0 Cable로 연결하여 커널 모드로 디버깅하는 방법에 대해서 알아보도록 합시다.

 

 

※ Prerequisites:

 

호스트 컴퓨터(Host Computer) : "Debugger"를 실행한 컴퓨터

타깃 컴퓨터(Target Computer) : "Debuggee"로 실행된 컴퓨터 (디버깅 대상이 된 컴퓨터)

 

USB 2.0 Cable을 기반으로 디버깅을 지원하기 위해, 호스트 컴퓨터의 윈도우즈 운영체제는 Windows 2000부터 Windows 8까지 사용할 수 있으며, 타깃 컴퓨터는 Windows Vista, Windows 7이나 Windows 8 버전으로 실행되어야 합니다.

 

Debugging over a USB 2.0 cable requires the following hardware:

  • A USB 2.0 debug cable. This cable is not a standard USB 2.0 cable because it has an extra hardware component that makes it compatible with the USB2 Debug Device Functional Specification. You can find these cables with an Internet search for the term USB 2.0 debug cable.

  • The host computer must have a USB 2.0 controller that is compatible with the Enhanced Host Controller Interface (EHCI) specification.

  • The target computer must have a USB 2.0 controller that is compatible with the EHCI specification and that supports kernel debugging. Not all EHCI-compatible controllers have this support.

 

USB 2.0 Cable은 별도로 준비하셔야 합니다만, 구매를 희망하신다면 잘 알려진 Ajays USB 2.0 Host-to-Host Debug Device and Cable(http://www.semiconductorstore.com/Ajays-Technology/)을 추천드립니다. (Ajays USB 2.0 Host-to-Host Debug Device and cable 아래 그림 참조)

이 글에서는 Ajays Host-to-Host debug Device와 Cable을 사용하는 것으로 가정하고 설명을 드리도록 하겠습니다.

대부분의 메인보드에서 EHCI 기반의 USB 2.0 controller를 지원하기 때문에 특별히 신경쓰지 않아도 됩니다만, 이를 지원하지 않는다면 USB 2.0 Cable로 디버깅을 할 수 없다는 것을 유념하시기 바랍니다.

 

먼저 WinDbg 디버거가 설치되어 있지 않다면 Host PC에서 WinDbg 디버거 설치를 하셔야 합니다만, 이때 WinDbg 디버거 버전은 반드시 6.5.3.8 이상으로 설치하셔야 합니다. 아시다시피, WinDbg는 마이크로소프트사에서 무료로 배포하고 있으며, 일반적으로 WDK(Windows Driver Kit)에 함께 패키징되어 있습니다. WDK(7600 이상 버전)를 설치할 때, Debug Tool 관련 체크 박스에 클릭하시면 함께 설치할 수 있습니다.

 

1. Setting up the Target Computer

 

[Step 1] 타깃 컴퓨터에서 CMD.EXE를 마우스 우클릭으로 팝업된 윈도우에서 [관리자 권한으로 실행]을 선택합니다. 커맨드 프롬프트 윈도우에서 다음과 같이 타이핑합니다.

 

bcdedit /debug off

 

[Step 2] 타깃 컴퓨터를 재부팅합니다.

 

[Step 3] 타깃 컴퓨터에서 UsbView Tool을 실행시킵니다. (UsbView Tool은 호스트 컴퓨터에 설치된 "Debugging Tools for Windows package"에 포함되어 있음)

 

[Step 4] UsbView Tool로 두 가지 작업을 해야 합니다.

① Finding a physical USB connector

첫 번째는 EHCI와 호환되는 USB 2.0 Host Controller를 찾는 작업입니다. 커널 디버깅을 할 수 있는 물리적인 USB 커넥터를 찾기 위해, USB 2.0 Cable을 USB 소켓에 연결하였을 때 USB Debug Device가 어느 곳에 나타나는지 확인해야 합니다. 이를 갱신하도록 하려면 UsbView Tool에서 [Refresh]를 체크하면 됩니다. Usb Debug Device를 EHCI 기반의 Host Controller의 Port 1로 연결했다면, UsbView Tool의 TreeView에 "USB 2.0 Debug Connection Device"를 확인할 수 있습니다. 여전히 확인할 수 없다면 다른 USB 소켓을 바꿔가면서 반복적으로 연결하는 작업을 해서 확인해야 합니다. 이렇게 확인하였음에도 불구하고 보여지는 USB 커넥터를 발견할 수 없다면, 그것은 USB 커널 디버깅을 위한 타깃 컴퓨터로 사용이 불가능합니다. 이는 EHC 기반의 USB 커넥터를 메인보드에서 지원하지 않는다는 의미가 됩니다.

 

② Identifying Bus number, Device number and Function number

두 번째 작업은 해당 USB 2.0 Host Controller의 버스 번호, 디바이스 번호 그리고 펑션 번호를 찾는 작업을 해야합니다. UsbView의 Tree View에서 "USB 2.0 Debug Connection Device"가 표시된 자식 노드 상위의 USB Host Controller의 16진수값을 상기합니다. (아래 그림 빨간색 밑줄과 동그라미 확인)

 

 

그 후, [장치관리자]를 실행시켜서 해당 Host Controller의 노드를 찾습니다. 그리고 해당 노드의 속성 정보를 클릭하면 PCI 버스 번호, 장치 번호, 기능 번호를 확인할 수 있습니다. 이것 역시 상기해야 합니다.

 

[Step 5] 다시 CMD.EXE를 관리자 권한으로 실행하고 다음과 같이 입력합니다.

 

(Windows 7 기준)

bcdedit /debug on

bcdedit /debgsettings usb targetname:TargetName

bcdedit /set "{dbgsettings}" busparams x.y.z

 

다시 위의 커맨드들을 설명드리면,

 

/debug on은 해당 타깃 컴퓨터를 디버깅 프로세서로 동작시키기 위한 옵션입니다.

 

위의 TargetName은 USB Cable이 연결된 타깃컴퓨터 대상을 식별하기 위한 문자열 값입니다. 다시 말해서 디버깅 대상이 되는 여러 대의 타깃 컴퓨터가 있다면 호스트 컴퓨터는 그 중에서 특정 하나를 선택하고 디버깅해야 할 것입니다. 바로 이를 위해 존재하는 문자열을 의미합니다.

 

busparams x.y.z가 Step 4에서 상기했던 버스 번호, 장치 번호, 기능 번호를 의미합니다. 예를 들어, 버스 번호 0, 장치 번호 19, 기능 번호 4라면, busparams 0.19.4 처럼 입력합니다. 이때, busparams의 값은 Windows 7에서는 Decimal 값으로 입력해야 함을 유의합니다.

 

[Step 6] 다시 타깃 컴퓨터를 재부팅하고 BIOS Setup Utility로 들어가서 [Advanced] 탭의 Legacy USB Support를 [Disabled]로 설정합니다.

 

 

 

2. Setting up the Host Computer

 

[Step 1] USB 2.0 debug cable 양쪽을 호스트와 타깃 컴퓨터에 연결합니다. 당연히 조금 전에 언급했던 것 처럼, EHCI와 호환이 되는 USB 2.0 Host Controller와 반드시 연결해야 합니다.

 

USB Cable을 연결하면, USB Debug 드라이버가 자동적으로 설치될 수도 있고 안될 수도 있습니다. 만약에 장치관리자에서 확인하여 !로 표시된다면 수동적으로 드라이버를 설치해야 합니다. 그 절차는 아래와 같습니다.

 

a.[장치관리자]에서 USB 2.0 debug cable를 연결하였을 때 !로 나타나는 노드를 찾음

b.노드의 속성 페이지에서 드라이버 업데이트 혹은 인스톨을 선택

c.드라이버 설치 마법사에서 "Debugging Tools for Windows package"에 있는 usb2dbg.inf을

  찾아서 설치

d.설치 마법사를 완료

 

[Step 2] 호스트 컴퓨터에서 첫 번째 USB Port를 찾습니다.

USB 버스를 통해서 디버깅을 수행하기 위해, Ajays device output port는 반드시 USB Port 1에 연결되어야 합니다(이는 호스트 컴퓨터에서만 해당하는 규칙임을 유의). 타깃 컴퓨터에서 UsbView를 사용해서 확인했던 것처럼, 마찬가지로 호스트 컴퓨터에서 USB Port 1를 찾기 위해, 순차적으로 Ajays Debug Cable을 연결해서 USB View에서 Refresh하여 확인하도록 합니다.

(아래 그림 참조. 이 그림에서는 Loc51이 USB Port 1에 해당함)

 

 

[Step 3] 호스트 컴퓨터에서 설치된 WinDbg를 실행하여 메인 메뉴에서 [File]-[Kernel Debug]를 선택합니다. 그리고 USB 2.0 탭을 선택하고 Target Name에 타깃 컴퓨터에서 입력했던 문자열 값을 동일하게 입력하고 OK 버튼을 클릭합니다.

 

WinDbg를 실행할 때마다 이렇게 작업하는 것이 번거롭다면, WinDbg.exe를 선택하고 우클릭해서 속성을 클릭하여 "대상"에 아래와 같이 입력합니다.

windbg.exe -b -k usb2:targetname=tagetname

이렇게 설정하면, WinDbg를 실행할 때마다 자동으로 지정된 Target Name으로 연결합니다.

 

3. 호스트 컴퓨터와 타깃 컴퓨터의 디버깅 연결

위의 모든 과정에서 설명드렸던 설정을 완료하셨다면, 호스트 컴퓨터에 설치된 WinDbg를 실행합니다. 그러고나서 타깃 컴퓨터를 재부팅합니다. 성공적으로 타깃 컴퓨터가 연결되었다면 아래의 그림과 같이 출력될 것입니다. 여기서 [Ctrl] + [Break]키를 누르면 소프트웨어 브레이크 포인트가 설정되고 타깃 컴퓨터는 HALT 상태로 대기하게 됩니다.

 

[Notes and References]

http://msdn.microsoft.com/en-us/library/windows/hardware/ff556869(v=vs.85).aspx

http://www.apriorit.com/our-company/dev-blog/210-win-debug-with-usb

http://blogs.msdn.com/b/usbcoreblog/archive/2010/10/25/setting-up-kernel-debugging-with-usb-2-0.aspx

 

그럼 여기까지 마무리하도록 하겠습니다. 좋은 주말 보내세요.

 

 

Written by Simhyeon, Choe

 

2013. 9. 12. 00:53

Device and Driver Layering I

오늘은 디바이스와 드라이버 레이어에 대해 공부해 봅시다.

 

Windows Driver Model(이하 WDM)은 아래 그림과 같이 드라이버 레이어를 표현하고 있습니다.

 

 

 

  일반적으로 디바이스 오브젝트의 스택은 위의 그림처럼 표현합니다. (디바이스에 따라 디바이스 스택은 위의 그림보다 계층이 적을 수도 혹은 보다 많을 수도 있음을 유의하셔야 합니다) 우선 디바이스 오브젝트를 정의하자면, 이것은 소프트웨어가 하드웨어를 관리하기 위해 시스템이 생성한 데이터 스트럭쳐라고 할 수 있습니다. 하나의 디바이스 오브젝트는 I/O REQUEST를 처리하기 위한 논리적, 가상 혹은 물리적인 디바이스를 의미합니다. 전혀 관련이 없는 다른 개념이지만 좀 더 이해를 돕고자 비유한다면, 우리는 객체 지향에서 어떤 기능과 속성을 포함하는 클래스라는 용어를 알고 있습니다. 그리고 클래스로 각기 다른 속성값을 가지고 있는 메모리에 존재하는 객체나 인스턴스로 생성하여 이를 표현합니다. 이 비유에서 클래스는 논리적인 디바이스, 가상의 디바이스나 물리적인 디바이스를 의미합니다. 그리고 객체는 디바이스의 고유의 속성을 표현하기 위한 디바이스 오브젝트로 비유할 수 있습니다. 이 개념 비유는 절대적인 비유라고 할 수 없으며, 단지 이해를 돕기 위해서 이렇게 설명을 드립니다. 그래서 물리적인 디바이스 하나를 위해, 많은 디바이스 오브젝트가 존재할 수 있습니다. 디바이스 스택에서 가장 낮은 레벨의 디바이스 오브젝트는 PDO(Physical Device Object)라고 하며, 디바이스 스택에서 중간 계층 레벨에 존재하는 디바이스 오브젝트는 FDO(Functional Device Object)라고 합니다. 그리고 위의 그림에서 보이는 것과 같이, FDO의 위와 아래에는 하나 이상의 FiDO(Filter Device Object)가 위치할 수도 있습니다. 통상 FDO 위에 위치한 Filter Device Object는 Upper filter라고 하며, FDO와 PDO 사이에 위치한 Filter Device Object는 Lower filter라고 정의합니다.

  그렇다면 디바이스 스택은 언제 구성하게 될까요? 간략히 순서를 설명하면, 시스템을 부팅하는 동안 버스 드라이버는 버스에 연결된 디바이스를 열거하고 각 디바이스들의 PDO를 생성합니다. 그리고 PnP Manager는 버스 드라이버가 생성한 PDO list를 참조하여 각 드라이버의 엔트리 포인트인 DriverEntry를 호출하여 콜백 루틴을 초기화하고 AddDevice로 디바이스를 위한 FDO를 생성하고 이를 디바이스 스택에 추가합니다. 물론, 여전히 PDO와 FDO 개념에 대한 감이 오지 않을 것이라고 생각합니다. 한 가지 예를 들어 보도록 하겠습니다. 컴퓨터에 연결된 키보드 하나가 연결되어 가정합시다. 키보드는 흔히 우리가 잘 알고 있는 디바이스입니다. 당연히 키보드의 입출력을 처리하기 위한 키보드 디바이스 드라이버가 필요할 것입니다. 위에서 부팅 과정 중에 버스 드라이버가 모든 디바이스들을 열거한다고 하였습니다. 당연히 키보드도 디바이스기 때문에 열거가 되겠지요. 여기서 버스 드라이버가 인식한 키보드 장치를 관리하기 위해 생성한 객체가 바로 PDO(Physical Device Object)가 됩니다. 자, 그럼 생성하고 나서 키보드가 동작을 해야되겠죠? 이에 키보드 드라이버는 키보드 기능 동작에 관한 세부적인 설명을 기술한 FDO(Functional Device Object)를 생성합니다.

  위에서 언급한 것처럼, 버스 드라이버가 디바이스의 PDO를 생성하고 해당 디바이스의 드라이버에서 구체적으로 기능적인 역할을 위해 FDO를 생성한다고 하였습니다. 그 이후의 동작 과정을 살펴보면, PnP Manager가 버스 드라이버에 의해 생성된 PDO List를 참조하여 디바이스 스택의 중간 계층에 위치한 Filter와 Function 드라이버를 찾기 위해 레지스트리 데이터 베이스를 조사합니다. 여기서 레지스트리 데이터 베이스는 디바이스 드라이버에 대한 여러가지 정보를 가지고 있는데, 특정 레지스트리 엔트리에서 디바이스 스택상에 순서대로 스택을 구성할 드라이버를 정의하고 있습니다. 그다음 PnP Manager는 가장 낮은 레벨의 Filter Driver를 로딩하고 Object를 생성하고나서 AddDevice Function을 호출합니다. 그리고 여기에서 FiDO(Filter Device Object)를 생성하고 이를 PDO와 연결하는 작업을 합니다. 마찬가지로 PnP Manager는 현재 구성중인 디바이스 스택에서 로딩하고 호출할 하위 Filter Driver, Function Driver, 상위 Fiter Driver의 Object를 각각 생성하고 차례대로 아래에서부터 서로 연결하여 디바이스 스택을 구성합니다. 결과적으로 위의 그림과 같이 디바이스 스택이 형성됩니다.

 

(참조 : http://www-user.tu-chemnitz.de/~heha/oney_wdm/ch02b.htm)

 

 

시간이 늦었으니, 오늘은 간단히 여기까지만 정리하도록 하겠습니다.

 

 

Written by Simhyeon, Choe