ISLab Flash Team Ch 9. Hardware Initialization
ISLab Flash Team Made By Povolon Ch 6. 초기화 및 정리 루틴 2 Contents 1.Plug and Play Architecture 2.The Role of the Registry for Legacy Drivers 3.Detecting Devices with Plug and Play 4.The Role of Driver Layers in Plug and Play 5.New WDM IRP Dispatch Functions 6.Device Enumeration 7.Device Interface 8.Summary
ISLab Flash Team 1. Plug and Play Architecture 2. The Role of the Registry for Legacy Driver
ISLab Flash Team Made By Povolon Ch 6. 초기화 및 정리 루틴 4 Goals of Plug and Play Automatic detection of installed and removed hardware. Device must allow for software configuration Automatically load as needed by the OS Support Hot plugging of device
ISLab Flash Team Made By Povolon Ch 6. 초기화 및 정리 루틴 5 Components of Plug and Play User Mode Kernel Mode Setup & Config Component Registry & INF Files I/O Mgr PnP Mgr Executive PnP Mgr Power Mgr WDM Drivers NT PnP Drivers HAL
ISLab Flash Team Made By Povolon Ch 6. 초기화 및 정리 루틴 6 The Role of Registry for Legacy Drivers Techniques used by NT OS & Drivers –Installation program 에 의존해서 Driver 에서 사용할 자원과 디바이스를 규정 –Driver 는 각 Device 가 사용할 하드웨어 자원을 리스트로 유지, DriverEntry Routine 에서 적절히 할당 및 Device 객체 생성 –NT OS 는 Preboot 과정에서 적당히 Device 와 자원을 탐색해서 Booting 시에 Reporting 및 Registry 에 저장 정규화된 설정처리를 위해 자동 감지 기능 초기화 과정에 하드웨어 리스트 감지 및 디바이스 생성 수동으로도 동작 가능 ( 드라이버 중심 ) 실시간 삽입 (Hot Plug in) 에 따른 Load( 디바이스중심 ) 드라이버 환경에서의 호환성
ISLab Flash Team 3. Detecting Devices with Plug and Play 4. The Role of Driver Layers in Plug and Play
ISLab Flash Team Made By Povolon Ch 6. 초기화 및 정리 루틴 8 Detecting Devices with Plug and Play DriverEntry 는 초기 진입점 이지만, 드라이버 내의 다른 루틴의 주소 만 알려주는 역할을 함 -> 나머지는 AddDevice 에서 생성 NTSTATUS AddDeviceIRQL == PASSIVE_LEVEL ParameterDescription IN PDRIVER_OBJECT pDriverObject Pointer to Driver Object IN PDEVICE_OBJECT pdo Pointer to Physical Device Object Return value STATUS_SUCCESS STATUS_XXX – some error code Funtion Prototype for an AddDevice Routine
ISLab Flash Team Made By Povolon Ch 6. 초기화 및 정리 루틴 9 The Role of Driver Layers in Plug and Play WDM (Windows Driver Model) –Device 를 Stack 형태로 구현함 Physical Device Object (PDO) – 버스에 붙은 각각의 하드웨어를 위해 생성 – 저 수준의 디바이스를 제어함 Function Device Object (FDO) – 논리적이고 추상적인 각각의 기능을 상위 레벨의 소프트웨어에 제공 –Bus FDO –Nonbus FDO Filter Device Object –FDO 상, 하위에서 I/O 요청에 수정 이나 보다 향상된 서비스를 제 공
ISLab Flash Team Made By Povolon Ch 6. 초기화 및 정리 루틴 10 The Role of Driver Layers in Plug and Play Nunbu s FDO Device PDO Nunbu s FDO Device PDO Nunbu s FDO Device PDO Nunbu s FDO Device PDO … FDO PDO Filter DO … Device Stack
ISLab Flash Team Made By Povolon Ch 6. 초기화 및 정리 루틴 11 AddDevice Routine 을 호출하는 알고리즘 1.System Registry 에 있는 모든 버스를 탐색, 열거 2. 버스 드라이버가 load 3. 버스에 존재하는 디바이스 열거 및 PDO 생성 4. 드라이버를 정의한 Registry 에서 Filter DO 와 FDO 를 위 한 Device Class 를 찾음 5.Filter Driver 나 Function Driver 가 Load 되지 않았으면 Driver 를 load 하고 DriverEntry 호출 6.FDO 및 다른 디바이스 계층을 위한 AddDevice 를 호출 디 바이스 스택 구성 (IoCreateDevice, IoAttachDeviceToDeviceStack)
ISLab Flash Team Made By Povolon Ch 6. 초기화 및 정리 루틴 12 Device Stack 디바이스 스택의 요소는 각 드라이버의 디바이스 Extension 구조체에 연관관계를 유지 or pointer 공간을 예약 하위 디바이스가 초기화 하는 동안 상위 디바이스 포인터는 하위 디 바이스가 알려진 디바이스 타입이어야 안정적인 초기화가 가능함 디바이스 스택에서는 어떤 드라이버도 자신의 하위 드라이버보다 우 선할 수 없다 PDEVICE_OBJECT IoAttachDeviceToDeviceStack IRQL == PASSIVE_LEVEL ParameterDescription IN PDEVICE_OBJECT pThisDevice Push 할 DO pointer IN PDEVICE_OBJECT pdoPointer to Physical Device Object Return value Top 에 있는 DO pointer Funtion Prototype for IoAttachDeviceToDeviceStack
ISLab Flash Team Made By Povolon Ch 6. 초기화 및 정리 루틴 13 AddDevice NTSTATUS AddDevice ( IN PDRIVER_OBJECT pDriverObject, IN PDEVICE_OBJECT pdo) { NTSTATUS status; PDEVICE_OBJECT pfdo; PDEVICE_EXTENSION pDevExt; static int ulDeviceNumber = 0; // 내부 디바이스 이름 초기화 CUString devName("\\Device\\MINPNP"); devName += CUString(ulDeviceNumber); // 새로운 디바이스 객체 생성 status = IoCreateDevice( pDriverObject, sizeof(DEVICE_EXTENSION), &(UNICODE_STRING)devName, FILE_DEVICE_UNKNOWN, 0, FALSE, &pfdo ); if (!NT_SUCCESS(status)) return status; // Device Extension 초기화 pDevExt = (PDEVICE_EXTENSION)pfdo->DeviceExtension; pDevExt->pDevice = pfdo;// back pointer pDevExt->DeviceNumber = ulDeviceNumber; pDevExt->ustrDeviceName = devName; pDevExt->pIntObj = NULL; pDevExt->bInterruptExpected = FALSE; pDevExt->state = Stopped;
ISLab Flash Team Made By Povolon Ch 6. 초기화 및 정리 루틴 14 AddDevice(Cont.) // 새로 생성한 fdo 를 스택 레이어의 맨 위에 쌓는다 (Push) pDevExt->pLowerDevice =// downward pointer IoAttachDeviceToDeviceStack( pfdo, pdo); // 상위 디바이스 객체의 포인터를 초기화 하기 위하여 상위 디바이스의 오프셋을 알아내고 하위 // 디바이스 익스텐션의 형변환을 수행 // PLOWER_DEVEXT pLowerDevExt = (PLOWER_DEVEXT) // pDevExt->pLowerDevice->DeviceExtension; // pLowerDevExt->pUpperDevice = pfdo; // Symbolic Link Name 의 초기화 및 생성 CUString symLinkName("\\??\\MPNP"); symLinkName += CUString(ulDeviceNumber+1);// 1 부터 시작함 pDevExt->ustrSymLinkName = symLinkName; status = IoCreateSymbolicLink( &(UNICODE_STRING)symLinkName, &(UNICODE_STRING)devName ); if (!NT_SUCCESS(status)) { // 생성에 실패하면 디바이스 객체를 삭제 IoDeleteDevice( pfdo ); return status; } // 완료 return STATUS_SUCCESS; }
ISLab Flash Team 5. The New WDM IRP Dispatch Function
ISLab Flash Team Made By Povolon Ch 6. 초기화 및 정리 루틴 16 Dispatch Function for Plug and Play 드라이버의 역할 – 디바이스에 요구되는 하드웨어 자원을 예약, 설정 – 하드웨어를 사용하기 위한 하드웨어 초기화 -> IRP_MJ_PNP 가 호출 되었을 때 수행 PnP Events – 디바이스 초기화 ( insertion ) – 디바이스 셧 다운 ( removal ) – 설정 요청 ( Configuration queries ) -> PnP IRP 코드를 PnP Manager 가 드라이버에게 송신 IRP_MJ_PNP 의 단일 dispatch routine 을 사용 -> Miner Code 를 사용한 루틴을 구성 (IRP_MN_XXX)
ISLab Flash Team Made By Povolon Ch 6. 초기화 및 정리 루틴 17 IRP Minor subcode NTSTATUS DispPnp ( IN PDEVICE_OBJECT pDO, IN PIRP pIrp) { // IRP Stack location 을 획득 ( Indexing ) PIO_STACK_LOCATION pIrpStack; pIrpStack = IoGetCurrentIrpStackLocation ( pIrp ); switch (pIrpStack->MinorFunction) { case IRP_MN_START_DEVICE : … case IRP_MN_STOP_DEVICE : … default : // 지원하지 않는 기능을 하위로 내려보냄 return PassDownPnP( pDO, pIrp ); } // switch 구문 각각의 모든 경우는 호출된 결과로 리턴함 } pDriverObject->MajorFuction[ IRP_MJ_PNP ] = DispPnp; Minor Function Dispatch Routine Major Function Dispatch Routine
ISLab Flash Team Made By Povolon Ch 6. 초기화 및 정리 루틴 18 Required Plug and Play IRPs PnP IRP Minor CodeMeaning IRP_MN_START_DEVICE 특정 자원에 대한 디바이스의 초기화 or 재 초기화 요청 IRP_MN_QUERY_STOP_DEVICE 디바이스를 정지 가능한지 확인 요청 IRP_MN_STOP_DEVICE 디바이스를 정지 시키는 요청 IRP_MN_CANCEL_STOP_DEVICE 정지 요청을 취소하는 요청 IRP_MN_QUERY_REMOVE_DEVIC E 안전하게 제거 가능한지 요청 IRP_MN_REMOVE_DEVICE 디바이스 제거 요청 IRP_MN_CANCEL_REMOVE_DEVIC E 제거요청을 취소하는 요청 IRP_MN_SURPRISE_REMOVAL 디바이스가 제거된다는 경고 없이 제거되는 경우의 요청 WDM 과 호환되기 위해서 드라이버는 반드시 디바이스의 각 객체 타입 에 따라 PnP IRP 에 대한 지원을 해야 함
ISLab Flash Team Made By Povolon Ch 6. 초기화 및 정리 루틴 19 PDO Plug and Play 추가적인 상황을 드라이버에서 구현할 수 있도록 핸들링 함 PnP IRP Minor CodeMeaning IRP_MN_QUERY_CAPABILITIES 디바이스가 지원하는 특성을 질의 ex) lock, hot plug in, eject … IRP_MN_QUERY_DEVICE_RELATION S 해당 디바이스와 관계된 디바이스 정보를 요청 IRP_MN_QUERY_INTERFACE 특정 인터페이스를 지원하는지 확인 요청 IRP_MN_EJECT 디바이스를 슬롯에서 뽑을 때의 요청 IRP_MN_SET_LOCK 디바이스를 잠글 때 요청
ISLab Flash Team Made By Povolon Ch 6. 초기화 및 정리 루틴 20 Prestart device states Device not present Device is present Device is enumerated Drives loaded & initialized FDO & Filter DOs created & stacked Device Enumerated AddDevice() PnP Manager loads driver & invokes DriverEntry Bus driver enumerates Device Physically inserted
ISLab Flash Team Made By Povolon Ch 6. 초기화 및 정리 루틴 21 Post-start device states Device not present Surprise removal Remove pending Stopped state Stop pending Device started IRP_MN_SURPRISE_REMOVAL IRP_MN_REMOVE_DEVICE IRP_MN_QUERY _REMOVE_DEVICE IRP_MN_CANCEL _REMOVE_DEVIC E IRP_MN_QUERY _STOP_DEVICE IRP_MN_CANCEL _STOP_DEVICE IRP_MN_STOP_DEVICE IRP_MN_START_DEVICE
ISLab Flash Team Made By Povolon Ch 6. 초기화 및 정리 루틴 22 Passing Down PnP Requests PnP Manager 는 항상 Device Stack 의 최상단에 위치한 디바이스의 드라이버로 PnP 요청을 보냄 요청의 처리가 될때까지 스택을 따라 내려보냄 IoCopyCurrentStackLocationToNext 와 IoCallDriver 를 호 출하여 디바이스 스택을 따라 내려감 상위 드라이버에서 하위 드라이버의 처리를 기다릴 필요 가 없을 경우 현재 IRP 스택 로케이션을 Skip 하고 완료 루 틴으로 IRP 처리의 신뢰성을 보장 NTSTATUS PassDownPnP( IN PDEVICE_OBJECT pDO, IN PIRP pIrp) { IoSkipCurrentIrpStackLocation( pIrp ); PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION) pDO- >DeviceExtension; return IoCallDriver(pDevExt-> pLowerDevice, pIrp); }
ISLab Flash Team Made By Povolon Ch 6. 초기화 및 정리 루틴 23 I/O Completion Routines VOID IoSetCompletionRoutineIRQL <= PASSIVE_LEVEL ParameterDescription IN PIRP pIrp IRP 의 포인터 IN PIO_COMPLETION_ROUTINE CompletionRoutine IRP 완료시에 제어권을 받을 수 있는 함수 포인터 IN PVOID pContext 완료 루틴으로 전달될 인자 IN BOOLEAN bInvokeOnSuccess IRP 가 성공하면 호출하도록 지정 IN BOOLEAN bInvokeOnError IRP 가 실패하면 호출하도록 지정 IN BOOLEAN bInvokeOnCancel IRP 가 취소되면 호출하도록 지정 Return value void Funtion Prototype for IoSetCompletionRoutine IoSetCompletionRoutine 을 사용하여 상위레벨의 드라이버에 등록 하위레벨 드라이버에서 완료하면 IoCompleteRequest 호출 하부에서 상부로 차례로 올라오면서 완료루틴이 호출됨
ISLab Flash Team Made By Povolon Ch 6. 초기화 및 정리 루틴 24 I/O Completion Routines (cont.) NTSTATUS OnIoCompletionIRQL == ??? ParameterDescription IN PDEVICE_OBJECT pDevObj 디바이스 객체 포인터 IN PIRP pIrp 완료된 IRP 의 포인터 IN PVOID pContext IoSetCompletionRoutine 에서 전달받은 인 자 Return value STATUS_MORE_PROCESSING_REQUIRED STATUS_SUCCESS Funtion Prototype for I/O Completion Routine 가장 하위의 드라이버만 예외 완료루틴 (OnIoCompletion) 의 IRQL 은 예측 불가능 함 PnP 핸들러를 PASSIVE_LEVEL 에서 수행시키기 위해 커널 이벤트 객체를 사용함
ISLab Flash Team Made By Povolon Ch 6. 초기화 및 정리 루틴 25 Bus Driver Plug and Play Requests 버스 드라이버에서 지원하는 PnP IRP Minor Code PnP IRP Minor CodeMeaning IRP_MN_QUERY_RESOURCES 부팅 설정 자원을 요청 IRP_MN_QUERY_RESOURCE_ REQUIREMENT 디바이스를 위한 자원 정보를 요청 IRP_MN_QUERY_ID 디바이스의 인스턴스 ID 를 요청 IRP_MN_QUERY_DEVICE_TEXT 디바이스에 대한 설명이나 위치를 요청 IRP_MN_QUERY_BUS_INFORMATION 버스의 정보를 요청 IRP_MN_READ_CONFIG 버스의 설정영역을 읽는 요청 IRP_MN_WRITE_CONFIG 버스의 설정영역에 쓰는 요청
ISLab Flash Team 6. Device Enumeration
ISLab Flash Team Made By Povolon Ch 6. 초기화 및 정리 루틴 27 Device Enumeration PnP 구성 관리자는 시스템 상에 발견된 하드웨어를 열거 IRP_MN_START_DEVICE 를 통해서 디바이스에 자원을 할당, 제공 받을 수 있음 하드웨어 자원의 할당은 버스, 디바이스 하드웨어, PnP Manager, 디바이스 드라이버를 모두 포함하는 동적인 상 호 처리 과정
ISLab Flash Team Made By Povolon Ch 6. 초기화 및 정리 루틴 28 Hardware Resource Descriptors IRP_MN_START_DEVICE 를 받으면 IRP 스택 내의 두개 의 필드에 하드웨어 자원을 리스트와 한다 (Parameters.StartDevice.AllocatedResourcesTranslated, Parameters.StartDevice.AllocatedResources) CM_RESOURCE_LIST Count LIST[] CM_RESOURCE_DESCRIPTO R Interface Type BusNumber PartialResourceList CM_PARTIAL_RESOURCE_LIST Version Revision Count Partial Descriptors[] CM_PARTIAL_RESOURCE_DESCRIPTOR Type ShareDisposition Flags Union u … … … Port Interrupt Memory DMA FDO Driver Ext.
ISLab Flash Team Made By Povolon Ch 6. 초기화 및 정리 루틴 29 Using Hardware Resources Within the Driver Raw resource ( 원본 그대로의 자원 ) – 버스의 상대적인 주소 (port, IRQLs, DMA Channel) –Translate resource 와 1:1 대응 관계를 가짐 ( 해석된 자원 ) –HAL 매크로들은 Translate resource 를 인자로 받음 자원의 제한 –IRP_MN_FILTER_RESOURCE_REQUIREMENTS 를 호출 –PnP Manager 에서 할당 받은 자원 리스트를 수정 ( 삭제 ) 가능
ISLab Flash Team 7. Device Interface
ISLab Flash Team Made By Povolon Ch 6. 초기화 및 정리 루틴 31 Interface Definition 구현자와 호출자 간의 함수 호출에 관련된 단순한 명세 혹 은 약속 Plug and Play 를 구현하면서 디바이스 드라이버로 하여 금 사용자 모드 코드로 인터페이스를 확장 하도록 함 Interface 의 특징 – 임의로 변경 되어서는 안됨 – 유일한 숫자나 Interface Type(ID) 로 식별가능 – 드라이버에서 제공되는 인터페이스는 Application 에서도 인식 – 드라이버에서 사용하는 수준과 같은 기능을 보장
ISLab Flash Team Made By Povolon Ch 6. 초기화 및 정리 루틴 32 Interface Construction 적당한 ID 가 생성되면, 명세를 위한 함수 포인터를 가지는 구조체로 생성함 C++ 에서는 상속기법으로 정의 가능 Typedef VOID (*PINTERFACE_REFERENCE)(PVOID pContext); Typedef VOID (*PINTERFACE_DEREFERENCE)(PVOID pContext); Typedef struct _INTERFACE { USHORTSize; USHORTVersion; PVOIDContext; PINTERFACE_REFERENCE InterfaceReference; PINTERFACE_DEREFERENCE InterfaceDereference; // 인터페이스 명세 엔트리를 여기에 작성함 }INTERFACE, *PINTERFACE
ISLab Flash Team Made By Povolon Ch 6. 초기화 및 정리 루틴 33 Registering and Enabling an Interface 인터페이스 생성 후 AddDevice 내의 IoRegisterDeviceInterface 함수 를 통해 Registering 시스템에 생성된 Symbolic Link Name 은 System Registry 에 보존됨, Device Extension 에도 저장 NTSTATUS IoRegisterDeviceInterface IRQL == PASSIVE_LEVEL ParameterDescription IN PDEVICE_OBJECT pDO 물리 디바이스 객체 포인터 IN CONST GUID *pInterfaceClassGuid Interface 의 ID 포인터 IN PUNICODE_STRING refString ID 의 혼동을 피하기위한 추가 문자열 OUT PUNICODESTRING SymbolicLinkName 드라이버와사용자 모드 코드를 interface 하 기 위해 지정한 이름 Return value STATUS_SUCCESS STATUS_INVALID_DEVICE_REQUEST Function Prototype for IoRegisterDeviceInterface
ISLab Flash Team Made By Povolon Ch 6. 초기화 및 정리 루틴 34 Registering and Enabling an Interface(cont.) IRP_MV_START_DEVICE 의 routine 이 호출되면 활성화 시킴 IoSetDeviceInterfaceState 함수로 Enable or Disable NTSTATUS IoSetDeviceInterfaceState IRQL == PASSIVE_LEVEL ParameterDescription IN PUNICODESTRING SymbolicLinkName 등록시 사용된 참조이름 IN BOOLEAN bEnableInterface TRUE - Enable FALSE - Disable Return value STATUS_SUCCESS STATUS_OBJECT_NAME_NOT_FOUND Function Prototype for IoSetDeviceInterfaceState
ISLab Flash Team Made By Povolon Ch 6. 초기화 및 정리 루틴 35 Registering and Enabling an Interface(cont.) IRP_MN_QUERY_INTERFACE 를 통해서 kernel Mode 로 사용 Parameters.QueryInterface.Interface field 에 호출자에 할 당된 구조체 Interface 를 구현한 함수의 pointer or Data 는 드라이버가 책임을 지고 유효한 값으로 채움
ISLab Flash Team Summary
Made By Povolon Ch 6. 초기화 및 정리 루틴 37 Summary 레거시 드라이버를 단순한 형태의 WDM 드라이버로 변환