💻
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
  • 애플리케이션 만들기
  • UEFI_HII_RESOURCE_SECTION
  • 유형이 'HII'인 PE/COFF 리소스
  1. UEFI 개발
  2. HII

50.UEFI_HII_RESOURCE_SECTION을 사용하여 문자열 패키지와 함께 HII 패키지 목록 게시하기

이번 장에서는 애플리케이션이 HII 문자열 패키지를 게시할 수 있는 또 다른 방법을 살펴본다. 이번에는 결과 EFI 파일 PE/COFF 리소스에 HII 데이터를 포함하는 것에 대해 알아본다.

애플리케이션 만들기

스크립트를 써서 평소와 같이 애플리케이션을 만든다.

./createNewApp.sh HIIStringsUNIRC

우리의 DSC 패키지 파일 UefiLessonsPkg/UefiLessonsPkg.dsc에 추가한다.

[Components]
  ...
  UefiLessonsPkg/HIIStringsUNI/HIIStringsUNI.inf

마지막으로 패키지 목록에 대한 GUID가 필요하며 패키지 DEC 파일인 UefiLessonsPkg/UefiLessonsPkg.dec에서 선언해준다.

[Guids]
  ...
  gHIIStringsUNIRCGuid = { 0x785693b4, 0x623e, 0x40fa, { 0x9a, 0x45, 0x68, 0xda, 0x38, 0x30, 0x89, 0xdd }}

이제 HIIStringsUNI 앱과 유사하도록 애플리케이션 파일을 수정해준다. Strings.uni 파일을 만들고 애플리케이션의 INF 및 *.c 파일을 수정해야한다.

  • UefiLessonsPkg/HIIStringsUNIRC/HIIStringsUNIRC.inf

  • UefiLessonsPkg/HIIStringsUNIRC/HIIStringsUNIRC.c

  • UefiLessonsPkg/HIIStringsUNIRC/Strings.uni

모든 작업을 완료하면 HIIStringsUNI 애플리케이션과 동일한 결과를 얻을 수 있다.

FS0:\> HIIStringsUNIRC.efi
en-US ID=1: English
en-US ID=2: Hello!
en-US ID=3: Bye!
fr-FR ID=1: Francais
fr-FR ID=2: Bonjour!
fr-FR ID=3: Au revoir!
Best language ID=1: English
Best language ID=2: Hello!
Best language ID=3: Bye!
fr ID=3: Au revoir!

이제 애플리케이션을 수정할 준비가 다 되었다.

UEFI_HII_RESOURCE_SECTION

UefiLessonsPkg/HIIStringsUNIRC/HIIStringsUNIRC.inf에 다음을 추가한다.

[Defines]
  ...
  UEFI_HII_RESOURCE_SECTION      = TRUE

UEFI_HII_RESOURCE_SECTION 플래그는 HII 리소스 섹션이 PE 이미지로 생성되는지 여부를 지정한다. 애플리케이션을 빌드하면 다음 오류로 인해 애플리케이션을 빌드할 수 없다.

UefiLessonsPkg/HIIStringsUNIRC/HIIStringsUNIRC.c:15:42: error: ‘HIIStringsUNIRCStrings’ undeclared (first use in this function);

Build/UefiLessonsPkg/RELEASE_GCC5/X64/UefiLessonsPkg/HIIStringsUNIRC/HIIStringsUNIRC/DEBUG/HIIStringsUNIRCStrDefs.h를 보면 이 파일에 여전히 문자열 토큰이 포함되어 있지만 HIIStringsUNIRCStrings는 더 이상 여기에 존재하지 않는 것을 알 수 있다.

그리고 AutoGen.c 파일에는 더 이상 HIIStringsUNIRCStrings 배열 초기화 코드가 포함되어 있지 않다(Build/UefiLessonsPkg/RELEASE_GCC5/X64/UefiLessonsPkg/HIIStringsUNIRC/HIIStringsUNIRC/DEBUG/AutoGen.c).

이제 우리의 문자열이 결과로 나오는 *.efi 이미지의 특수 섹션으로 인코딩되어 들어가는 것이다.

이를 우리가 얻으려면 애플리케이션 EFI_HANDLE ImageHandle에서 프로토콜 EFI_HII_PACKAGE_LIST_PROTOCOL을 검색해야 한다.

다음은 Shell이 모든 프로그램을 로드하는 데 사용하는 EFI_BOOT_SERVICES.LoadImage() 함수에 대한 UEFI 스펙의 관련 내용이다.

Once the image is loaded, LoadImage() installs EFI_HII_PACKAGE_LIST_PROTOCOL on the handle if
the image contains a custom PE/COFF resource with the type 'HII'. The protocol's interface pointer points
to the HII package list which is contained in the resource's data
[Protocols]
  ...
  ## Include/Protocol/HiiPackageList.h
  gEfiHiiPackageListProtocolGuid  = { 0x6a1ee763, 0xd47a, 0x43b4, {0xaa, 0xbe, 0xef, 0x1d, 0xe2, 0xab, 0x56, 0xfc}}

우리의 INF 파일의 [Packages] 섹션에 MdeModulePkg/MdeModulePkg.dec가 이미 있으므로 이 GUID를 [Protocols] 섹션에 추가하기만 하면 된다.

[Protocols]
  gEfiHiiPackageListProtocolGuid

코드에서는 OpenProtocol UEFI 부트 서비스의 도움으로 애플리케이션의 ImageHandle 에서 PackageList 프로토콜을 얻을 수 있다.

...

EFI_STATUS
EFIAPI
UefiMain (
  IN EFI_HANDLE        ImageHandle,
  IN EFI_SYSTEM_TABLE  *SystemTable
  )
{
  EFI_STATUS Status;
  EFI_HII_PACKAGE_LIST_HEADER *PackageList;
  //
  // Retrieve HII package list from ImageHandle.
  //
  Status = gBS->OpenProtocol (
                  ImageHandle,
                  &gEfiHiiPackageListProtocolGuid,
                  (VOID **)&PackageList,
                  ImageHandle,
                  NULL,
                  EFI_OPEN_PROTOCOL_GET_PROTOCOL
                  );
  if (EFI_ERROR (Status)) {
    Print(L"Error! Can't open EFI_HII_PACKAGE_LIST_PROTOCOL\n");
    return Status;
  }
  ...

결과의 PackageList는 HIIStringsUNI 애플리케이션의 경우와 같이 StrGather 스크립트의 결과인 일부 size 헤더가 있는 문자열 패키지가 아니다. HIIStringsC 애플리케이션에서 수동으로 구성한 것과 같은 일반 PackageList이다. 따라서 HiiAddPackages 라이브러리 함수를 사용하는 대신 EFI_HII_DATABASE_PROTOCOL.NewPackageList()를 직접 사용해야 한다.

EFI_HII_HANDLE Handle;
Status = gHiiDatabase->NewPackageList(gHiiDatabase, PackageList, NULL, &Handle);
if (EFI_ERROR(Status))
{
  Print(L"Can't register HII Package list %g, status = %r\n", gHIIStringsUNIRCGuid, Status);
  return Status;
}

여기서는 gHiiDatabase를 사용했으므로 필요한 헤더인 #include <Library/UefiHiiServicesLib.h>를 추가하고 애플리케이션 INF 파일의 [LibraryClasses]에 UefiHiiServicesLib를 추가하는 것을 잊지 말자.

이제 애플리케이션을 빌드하고 실행해보면 모든 것이 정상인것을 확인할 수 있다.

FS0:\> HIIStringsUNIRC.efi
Status = Success
en-US ID=1: English
en-US ID=2: Hello!
en-US ID=3: Bye!
fr-FR ID=1: Francais
fr-FR ID=2: Bonjour!
fr-FR ID=3: Au revoir!
Best language ID=1: English
Best language ID=2: Hello!
Best language ID=3: Bye!
fr ID=3: Au revoir!

유형이 'HII'인 PE/COFF 리소스

objdump를 사용하여 애플리케이션 헤더를 살펴보자. -x 옵션을 사용하여 모든 헤더의 내용을 출력할 수 있다.

objdump -x  Build/UefiLessonsPkg/RELEASE_GCC5/X64/HIIStringsUNIRC.efi

화살표 뒤의 사항에 주의하면서 보자.

...

The Data Directory
Entry 0 0000000000000000 00000000 Export Directory [.edata (or where ever we found it)]
Entry 1 0000000000000000 00000000 Import Directory [parts of .idata]
Entry 2 00000000000023c0 00000180 Resource Directory [.rsrc]                <---------- Resource Directory 에 데이터가 존재한다.
Entry 3 0000000000000000 00000000 Exception Directory [.pdata]
Entry 4 0000000000000000 00000000 Security Directory
Entry 5 0000000000000000 00000000 Base Relocation Directory [.reloc]
Entry 6 00000000000022cc 0000001c Debug Directory
Entry 7 0000000000000000 00000000 Description Directory
Entry 8 0000000000000000 00000000 Special Directory
Entry 9 0000000000000000 00000000 Thread Storage Directory [.tls]
Entry a 0000000000000000 00000000 Load Configuration Directory
Entry b 0000000000000000 00000000 Bound Import Directory
Entry c 0000000000000000 00000000 Import Address Table Directory
Entry d 0000000000000000 00000000 Delay Import Directory
Entry e 0000000000000000 00000000 CLR Runtime Header
Entry f 0000000000000000 00000000 Reserved

...

The .rsrc Resource Directory section:
000  Type Table: Char: 0, Time: 00000000, Ver: 0/0, Num Names: 1, IDs: 0
010   Entry: name: [val: 80000048 len 3]: HII, Value: 0x80000018           <--------- Data 타입이 HII이다.
018    Name Table: Char: 0, Time: 00000000, Ver: 0/0, Num Names: 1, IDs: 0
028     Entry: name: [val: 80000050 len 3]: EFI, Value: 0x80000030
030      Language Table: Char: 0, Time: 00000000, Ver: 0/0, Num Names: 1, IDs: 0
040       Entry: name: [val: 80000058 len 3]: BIN, Value: 0x000060
060        Leaf: Addr: 0x002430, Size: 0x0000ea, Codepage: 0
 String table starts at offset: 0x48
 Resources start at offset: 0x70

Sections:
Idx Name          Size      VMA               LMA               File off  Algn
  0 .text         00001fc0  0000000000000240  0000000000000240  00000240  2**4
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
  1 .data         000001c0  0000000000002200  0000000000002200  00002200  2**4
                  CONTENTS, ALLOC, LOAD, DATA
  2 .rsrc         00000180  00000000000023c0  00000000000023c0  000023c0  2**2       <----- 여기에도 .rsrc가 표시된다.
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
SYMBOL TABLE:
no symbols

이제 UefiLessonsPkg/HIIStringsUNIRC/HIIStringsUNIRC.inf에 UEFI_HII_RESOURCE_SECTION을 주석 처리해준다.

[Defines]
  ...
  #UEFI_HII_RESOURCE_SECTION      = TRUE

애플리케이션 빌드 후에 objdump를 다시 한 번 실행해보면 다음과 같은 결과를 얻을 수 있다.

...

The Data Directory
Entry 0 0000000000000000 00000000 Export Directory [.edata (or where ever we found it)]
Entry 1 0000000000000000 00000000 Import Directory [parts of .idata]
Entry 2 0000000000000000 00000000 Resource Directory [.rsrc]                 <----- Resource directory 가 비어있다.
Entry 3 0000000000000000 00000000 Exception Directory [.pdata]
Entry 4 0000000000000000 00000000 Security Directory
Entry 5 0000000000000000 00000000 Base Relocation Directory [.reloc]
Entry 6 00000000000022cc 0000001c Debug Directory
Entry 7 0000000000000000 00000000 Description Directory
Entry 8 0000000000000000 00000000 Special Directory
Entry 9 0000000000000000 00000000 Thread Storage Directory [.tls]
Entry a 0000000000000000 00000000 Load Configuration Directory
Entry b 0000000000000000 00000000 Bound Import Directory
Entry c 0000000000000000 00000000 Import Address Table Directory
Entry d 0000000000000000 00000000 Delay Import Directory
Entry e 0000000000000000 00000000 CLR Runtime Header
Entry f 0000000000000000 00000000 Reserved

...                                                                          <----- .rsrc 리소스 디렉터리 섹션이 없다.

Sections:
Idx Name          Size      VMA               LMA               File off  Algn
  0 .text         00001fc0  0000000000000240  0000000000000240  00000240  2**4
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
  1 .data         000001c0  0000000000002200  0000000000002200  00002200  2**4   <---- 여기에도 .rsrc 섹션이 없다.
                  CONTENTS, ALLOC, LOAD, DATA
SYMBOL TABLE:
no symbols

이 버전의 애플리케이션을 실행하려고 하면 아래와 같이 실행된다.

FS0:\> HIIStringsUNIRC.efi
Error! Can't open EFI_HII_PACKAGE_LIST_PROTOCOL
Previous49.MODULE_UNI_FILE/PACKAGE_UNI_FILE/[UserExtensions.TianoCore."ExtraFiles"]의 도움으로 UNI 파일 선언하기Next51. UEFI APP에 메뉴얼 추가하기(shell의 -?와 help 옵션)

Last updated 2 years ago

에 따르면 EFI_HII_PACKAGE_LIST_PROTOCOL은 gEfiHiiPackageListProtocolGuid로 식별된다.

🖥️
https://github.com/tianocore/edk2/blob/master/MdePkg/MdePkg.dec