34. 간단한 UEFI 드라이버 생성

이번 장에서는 UEFI 드라이버를 생성한다.

지금까지는 UEFI 애플리케이션만 만들었다. 애플리케이션과 드라이버의 주요 차이점은 애플리케이션이 실행된 후 메모리에 언로드된다는 점이다. 하지만 드라이버는 메모리에 남아있다. 또한 다른 애플리케이션이 사용할 유용한 프로토콜을 제공하기도 한다.

가장 간단한 드라이버로 UefiLessonsPkg/SimpleDriver/SimpleDriver.inf를 생성한다.

[Defines]
  INF_VERSION                    = 1.25
  BASE_NAME                      = SimpleDriver
  FILE_GUID                      = 384aeb18-105d-4af1-bf17-5e349e8f4d4c
  MODULE_TYPE                    = UEFI_DRIVER
  VERSION_STRING                 = 1.0
  ENTRY_POINT                    = SimpleDriverEntryPoint

[Sources]
  SimpleDriver.c

[Packages]
  MdePkg/MdePkg.dec

[LibraryClasses]
  UefiDriverEntryPoint
  UefiLib

기존에 애플리케이션을 생성할 때 사용했던 application.inf 파일과 드라이버를 생성할 때 사용하는 driver.inf 파일의 차이는 아래와 같다.

  • MODULE_TYPEUEFI_DRIVER이다. (이전에는 항상 UEFI_APPLICATION을 사용했다.

  • ENTRY_POINTSimpleDriverEntryPoint이다. (이전에는 항상 UefiMain을 사용했지만, 드라이버는 Entry/Unload 함수로 작동하므로 적절한 이름을 지정한다.)

  • UefiDriverEntryPoint 라이브러리 클래스가 사용된다. (이전에는 항상 UefiApplicationEntryPoint를 사용했다.) UefiApplicationEntryPoint 라이브러리에 대해 궁금하다면 아래 링크를 통해 확인할 수 있다. https://github.com/tianocore/edk2/tree/master/MdePkg/Library/UefiDriverEntryPoint

이제 UefiLessonsPkg/SimpleDriver/SimpleDriver.c 소스 파일을 생성한다. 구현해야 할 유일한 함수는 entry 함수인 SimpleDriverEntryPoint 이다.

드라이버를 생성하기 위해 UefiLessonsPkg/UefiLessonsPkg.dscComponents에 추가한다.

아직은빌드를 시도하면 아래와 같은 이유로 실패한다.

애플리케이션을 만들 때와 마찬가지로 필요한 라이브러리를 찾아야 한다. 2개의 결과가 나오지만 필요한 라이브러리는 MdePkg의 것이므로 이것을 사용한다.

확인한 UefiDriverEntryPoint.int 파일의 경로를 UefiLessonsPkg/UefiLessonsPkg.dsc에 추가한다.

빌드 후 SimpleDriver.efi를 실행하면 아래와 같이 애플리케이션이 아니라는 메시지를 확인할 수 있다.

위 메시지를 통해서 알 수 있듯이 드라이버는 실행이 불가능하다. 그래서 드라이버를 로드하기 위해서 Shell에서 load명령어를 사용해야 한다.

load 명령어를 사용해 드라이버를 로드한다.

이제 dh 명령어로 드라이버 핸들을 살펴본다.

매개변수 없이 dh 명령어를 실행하면 시스템의 모든 핸들을 얻을 수 있다. 우리가 만든 드라이버는 맨 마지막에 확인할 수 있다.

핸들을 더 상세하게 확인할 수도 있다.

생성한 드라이버로 더 많은 인스턴스를 생성할 수 있으며, 많이 생성한다고 해서 문제되지 않는다.

dh 명령어를 통해 확인하면 드라이버 핸들이 여러 개인 것을 확인할 수 있다.

메모리에서 드라이버를 언로드하려면 unload 명령을 사용하면 된다.

unload 명령은 드라이버에 Unload 함수가 없기 때문에 지금은 사용할 수 없다. dh -d -v c0을 사용하면 Unload........: 0 부분을 확인할 수 있다.

따라서 드라이버를 언로드하려고 하면 오류가 발생한다.

dh 명령어를 실행하면 시스템에 드라이버 핸들이 여전히 존재하는 것을 볼 수 있다.

Unload 함수 추가

이제 언로드 함수를 드라이버에 추가한다. 아래 설정을 UefiLessonsPkg/SimpleDriver/SimpleDriver.inf에 추가한다.

UefiLessonsPkg/SimpleDriver/SimpleDriver.c에 함수를 추가한다.

새로 빌드하고 드라이버를 로드한 후 dh -d -v 명령어를 사용하면 위에서 확인한 결과와는 달리 Unload에 값이 들어간 것을 볼 수 있다.

출력된 결과를 통해 알 수 있듯이 언로드 문자열이 드라이버 언로드 함수에 대한 포인터로 채워진다.

드라이버를 언로드하기 전에 dmem을 통해 ImageBase 주소를 확인한다.

MZ 시그니처는 PE/COFF 이미지(*.efi 파일)의 헤더를 나타낸다. 그래서 실제 드라이버는 ImageBase에 존재한다.

이제 드라이버를 언로드 한다.

메모리를 다시 확인하면 아래와 같이 비어진 것을 확인할 수 있다.

드라이버를 새로 로드하면 기존에 사용했던 C0은 넘어가고 C1으로 핸들이 존재하는 것을 볼 수 있다.

Last updated