💻
UEFI 프로젝트
  • 🧑‍🏫프로젝트 개요
  • 📖UEFI 개념
    • 1. BIOS의 과거
    • 2. UEFI 개념
    • 3. BIOS vs UEFI
    • 4. UEFI 부팅 단계
  • 🖥️UEFI 개발
    • UEFI 개발 시작하기
      • 0. EDK II 빌드 환경 구성
      • 1. 간단한 EFI application 만들기
      • 2. 간단한 Pkg 만들기
      • 3. Hello World 출력하기
      • 4. 라이브러리와 Hello World
      • 5. Conf를 통한 Build 단순화
    • 핸들 및 프로토콜
      • 6. 핸들/프로토콜 데이터 베이스 구조 - Part 1
      • 7. 핸들/프로토콜 데이터 베이스 구조 - Part 2
      • 8. HandleProtocol API 함수 & ImageHandle 프로토콜을 통한 정보
      • 9. ProtocolsPerHandle API를 통한 ImageHandle 프로토콜 가져오기
      • 10. EFI_STATUS 타입 과 EFI_ERROR 매크로
    • 메모리 맵
      • 11. EFI 메모리 맵 정보 얻기
      • 12. EFI 메모리 맵을 리눅스 커널 스타일로 바꾸기
    • 명령줄 인수를 받는 간단한 앱 만들기
      • 13.ShellAppMain Entry point
      • 14.gRT->GetNextVariableName API를 사용하여 모든 변수 이름 및 GUID 가져오기
    • 부팅 옵션
      • 15. gRT->GetVariable API를 사용하여 부팅 변수 가져오기 및 구문 분석
      • 16. OVMF 이미지 내에 부팅 옵션 추가
      • 17. 부팅 옵션에 WaitForEvent 함수 추가
      • 18. ReadKeyStroke 함수로 사용자 입력 처리
      • 19. bcfg 명령어를 사용한 부팅 옵션 수정
    • PCD
      • 20. PCD 소개
      • 21. PCD 변수에 대한 Overriding
      • 22. Feature Flag PCD와 BOOLEAN FixedAtBuild PCD의 비교
      • 23. PatchableInModule PCD 및 GenPatchPcdTable/PatchPcdValue 유틸리티를 통해 PCD를 변경하는 방법
      • 24. Dynamic/DynamiEx PCDs
      • 25. PCD 더 알아보기
    • 테이블
      • 26. EFI_CONFIGURATION_TABLE에서 참조되는 테이블
      • 27. dmem/EFI_SMBIOS_PROTOCOL/smbiosview를 통해서 SMBIOS 정보 가져오기
      • 28. EFI_SHELL_PROTOCOL을 통하여 ACPI 테이블을 파일에 저장하기
      • 29. EFI_ACPI_SDT_PROTOCOL 및 ShellLib를 사용하여 ACPI BGRT 테이블에서 BMP 이미지 저장하기
    • PCI
      • 30. PCI 루트 브리지 찾은 후 시스템의 모든 PCI 기능 가져오기
      • 31. ShellLib/PrintLib 함수를 사용해 PCI Vendor/Device 정보 가져오기
      • 32. EFI_PCI_IO_PROTOCOL을 사용해 PCI Option ROM 이미지 표시
      • 33. EfiRom 유틸리티를 사용한 PCI Option ROM 이미지 파싱 및 생성
    • 드라이버 및 라이브러리
      • 34. 간단한 UEFI 드라이버 생성
      • 35. 애플리케이션에서 사용할 간단한 라이브러리 생성
      • 36. Library의 constructor와 destructor, NULL Library
      • 37. Shell에 acpiview 명령을 추가하는 방법 조사
      • 38. 사용자 지정 프로토콜을 만들고 사용하기
      • 39. RegisterKeyNotify / UnrigisterKeyNotify 함수를 사용해 단축키 기능을 추가하는 드라이버 만들기
      • 40. Key #### NVRAM 변수
    • 디버그
      • 41. DEBUG 출력문 내부 구조와 DEBUG 문 제어를 위한 PCD 분석, 그리고 OVMF 부트 로그 가져오기
      • 42. GDB를 이용한 Driver/Application 및 OVMF Debug
    • HII
      • 43. HII 데이터베이스 개념 및 출력
      • 44. HII 데이터베이스 내부
      • 45. EFI_HII_DATABASE_PROTOCOL의 NewPackageList를 사용하여 문자열 패키지가 포함된 문자열 목록 게시
      • 46. EFI_HII_DATABASE_PROTOCOL의 NewPackageList를 사용하여 문자열 패키지가 포함된 HII 패키지 목록 게시
      • 47. EFI_HII_DATABASE_PROTOCOL의 NewPackageList를 사용하여 문자열 패키지가 포함된 HII 패키지 목록 게시
      • 48. UNI 파일 및 HiiLib를 사용하여 HII String 패키지 게시 및 작업하기
      • 49.MODULE_UNI_FILE/PACKAGE_UNI_FILE/[UserExtensions.TianoCore."ExtraFiles"]의 도움으로 UNI 파일 선언하기
      • 50.UEFI_HII_RESOURCE_SECTION을 사용하여 문자열 패키지와 함께 HII 패키지 목록 게시하기
      • 51. UEFI APP에 메뉴얼 추가하기(shell의 -?와 help 옵션)
      • 52. Russian 글꼴 추가 - Part 1.
      • 53. Russian 글꼴 추가 - Part 2.
      • 54. EFI_HII_STRING_PROTOCOL의 NewString 및 SetString 함수를 사용하여 다른 언어에 대한 문자열 패키지를 동적으로 추가
      • 55. PlatformLangCodes EFI 변수 수정 및 다른 언어를 동적 추가하기
      • 56. 코드에서 FILE_GUID 및 BASE_NAME을 가져오기
    • VFR
      • 57. VFR을 사용해 간단한 폼 생성 및 EFI_FORM_BROWSER2_PROTOCOL.SendForm()를 통해 화면에 폼 표시하기
      • 58. VFR 요소 : subtitle 및 text
      • 59. 간단한 폼 애플리케이션을 UEFI 드라이버 Form으로 변환하기
      • 60. gRT->SetVariable() 함수를 사용한 UEFI 변수 생성, 변경 및 삭제
      • 61.dmpstore 명령을 사용하여 변수를 파일에 저장/로드하기
      • 62. UEFI Device path의 구조
      • 63. checkbox를 가진 HII 폼 만들기
      • 64. checkbox를 가진 HII폼 만들기
      • 65. VFR 추가 입력 요소 Part 1: number
      • 66. VFR 추가 입력 요소 Part 2: string
      • 67. VFR 추가 입력 요소 Part 3: date & time
      • 68. VFR 추가 입력 요소 Part 3: oneof & orderedlist
      • 69. VFR의 조건부 키워드
      • 70. VFR의 상수 및 연산자가 내장된 기본 조건문
      • 71. 기본 VFR 내장 문자열용 함수
      • 72. label 키워드를 이용하여 HII 양식에 동적 요소 추가하기
      • 73. VFR question 기본값 설정
  • 🔐UEFI 보안
    • 1. 개요
    • 2. 공격 벡터
    • 3. mitigation
    • 4. 정적 분석 방법
    • 5. 동적 분석 방법
Powered by GitBook
On this page
  1. UEFI 개발
  2. 핸들 및 프로토콜

9. ProtocolsPerHandle API를 통한 ImageHandle 프로토콜 가져오기

API를 통해서 간편하게 ImageHandle 프로토콜 가져오기

이전 장에서 설명한 이미지 핸들에 대한 프로토콜을 찾는 방식은 단순히 구조를 이해하기 위해서다. 동일한 결과를 UEFI API를 사용하면 더욱 간편하게 가져올 수 있다.

ProtocolsPerHandle -

EFI_BOOT_SERVICES.ProtocolsPerHandle()

Summary:
Retrieves the list of protocol interface GUIDs that are installed on a handle in a buffer allocated from pool.

Prototype:
typedef
EFI_STATUS
(EFIAPI *EFI_PROTOCOLS_PER_HANDLE) (
 IN EFI_HANDLE Handle,
 OUT EFI_GUID ***ProtocolBuffer,
 OUT UINTN *ProtocolBufferCount
 );

Parameters:
Handle The handle from which to retrieve the list of protocol interface GUIDs.
ProtocolBuffer A pointer to the list of protocol interface GUID pointers that are installed on Handle. This buffer is allocated with a call to the Boot Service EFI_BOOT_SERVICES.AllocatePool(). It is the caller's responsibility to call the Boot Service EFI_BOOT_SERVICES.FreePool() when the caller no longer requires the contents of ProtocolBuffer.
ProtocolBufferCountA pointer to the number of GUID pointers present in ProtocolBuffer.

Description:
The ProtocolsPerHandle() function retrieves the list of protocol interface GUIDs that are installed on Handle. The list is returned in ProtocolBuffer, and the number of GUID pointers in ProtocolBuffer is returned in ProtocolBufferCount.
If Handle is NULL or Handle is NULL, then EFI_INVALID_PARAMETER is returned.
If ProtocolBuffer is NULL, then EFI_INVALID_PAREMETER is returned.
If ProtocolBufferCount is NULL, then EFI_INVALID_PARAMETER is returned.
If there are not enough resources available to allocate ProtocolBuffer, then EFI_OUT_OF_RESOURCES is
returned.

Status Codes Returned:
EFI_SUCCESS	 	The list of protocol interface GUIDs installed on Handle was returned in
			ProtocolBuffer. The number of protocol interface GUIDs was
			returned in ProtocolBufferCount.
EFI_INVALID_PARAMETER 	Handle is NULL.
EFI_INVALID_PARAMETER 	ProtocolBuffer is NULL.
EFI_INVALID_PARAMETER 	ProtocolBufferCount is NULL.
EFI_OUT_OF_RESOURCES 	There is not enough pool memory to store the results.

해당 설명을 읽어보면 버퍼의 할당을 AllocatePool()을 통해서 자동적으로 해주며 해당 버퍼에 대한 해제는 FreePool()을 통해서 사용자가 직접 해야한다고 나와있다.

EFI_BOOT_SERVICES.FreePool()

Summary:
Returns pool memory to the system.

Prototype:
typedef
EFI_STATUS
(EFIAPI *EFI_FREE_POOL) (
  IN VOID *Buffer
);

Parameters:
Buffer Pointer to the buffer to free.

Description:
The FreePool() function returns the memory specified by Buffer to the system. On return, the
memory’s type is EfiConventionalMemory. The Buffer that is freed must have been allocated by
AllocatePool().

Status Codes Returned:
EFI_SUCCESS            The memory was returned to the system.
EFI_INVALID_PARAMETER  Buffer was invalid

API의 사용법에 대해서 숙지하고 있으니 ImageHandle 어플리케이션 아랫 부분에 추가를 시켜보겠다.

Print(L"________\n");
EFI_GUID **ProtocolGuidArray;
UINTN ArrayCount;
EFI_STATUS Status = gBS->ProtocolsPerHandle(ImageHandle,
                                            &ProtocolGuidArray,
                                            &ArrayCount);

if (Status == EFI_SUCCESS) {
  for (int i=0; i<ArrayCount; i++) {
    Print(L"%g\n", ProtocolGuidArray[i]);
  }
  FreePool(ProtocolGuidArray);
}

이외에도 FreePool 함수 사용을 위해서 헤더 파일을 추가 해야한다.

#include <Library/MemoryAllocationLib.h>
/**
  Frees a buffer that was previously allocated with one of the pool allocation functions in the
  Memory Allocation Library.

  Frees the buffer specified by Buffer.  Buffer must have been allocated on a previous call to the
  pool allocation services of the Memory Allocation Library.  If it is not possible to free pool
  resources, then this function will perform no actions.

  If Buffer was not allocated with a pool allocation function in the Memory Allocation Library,
  then ASSERT().

  @param  Buffer                The pointer to the buffer to free.

**/
VOID
EFIAPI
FreePool (
  IN VOID   *Buffer
  )
{
  EFI_STATUS    Status;

  Status = gBS->FreePool (Buffer);
  ASSERT_EFI_ERROR (Status);
}

추가로 FreePool에는 다른 라이브러리들의 구현이 필요하기 때문에 .dsc 파일의 [LibraryClasses] 부분에 추가가 필요하다.

MdePkg/Library/PeiMemoryAllocationLib/MemoryAllocationLib.c
MdePkg/Library/SmmMemoryAllocationLib/MemoryAllocationLib.c
MdePkg/Library/UefiMemoryAllocationLib/MemoryAllocationLib.c
[LibraryClasses]
  ...
  MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf
  ...

빌드 후 QEMU상에서 파일을 실행시키면 아래와 같은 화면을 볼 수 있으며 이는 이전에 핸들/프로토콜 데이터베이스를 통해서 구한 GUID 값과 동일한 것을 알 수 있다.

752F3136-4E16-4FDC-A22A-E5F46812F4CA
BC62157E-3E33-4FEC-9920-2D3B36D750DF
5B1B31A1-9562-11D2-8E3F-00A0C969723B
Previous8. HandleProtocol API 함수 & ImageHandle 프로토콜을 통한 정보Next10. EFI_STATUS 타입 과 EFI_ERROR 매크로

Last updated 2 years ago

일부 사람들은 해당 코드를 보고 gBs->FreePool을 사용하지 않고 FreePool을 사용한 것을 궁금해 할 수도 있다. 이는 아래의 파일에 정의가 되어서 문제가 생기지 않는 것이다. ()

🖥️
https://github.com/tianocore/edk2/blob/master/MdePkg/Library/UefiMemoryAllocationLib/MemoryAllocationLib.c