💻
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. HII

47. EFI_HII_DATABASE_PROTOCOL의 NewPackageList를 사용하여 문자열 패키지가 포함된 HII 패키지 목록 게시

파트 3: NewPackageList 및 GetString 프로토콜 함수를 사용하여 모든 것을 결합하기

이제 마침내 HII 데이터베이스에 패키지 목록을 등록할 수 있다. 다음은 또 한번 NewPackageList에 대한 설명이다.

EFI_HII_DATABASE_PROTOCOL.NewPackageList()

Summary:
Adds the packages in the package list to the HII database.

Prototype:
typedef
EFI_STATUS
(EFIAPI *EFI_HII_DATABASE_NEW_PACK) (
 IN CONST EFI_HII_DATABASE_PROTOCOL *This,
 IN CONST EFI_HII_PACKAGE_LIST_HEADER *PackageList,
 IN CONST EFI_HANDLE DriverHandle, OPTIONAL
 OUT EFI_HII_HANDLE *Handle
 );

Parameters:
This		A pointer to the EFI_HII_DATABASE_PROTOCOL instance
PackageList	A pointer to an EFI_HII_PACKAGE_LIST_HEADER structure
DriverHandle	Associate the package list with this EFI handle
Handle		A pointer to the EFI_HII_HANDLE instance
Description	This function adds the packages in the package list to the database and returns a handle. If there is a
		EFI_DEVICE_PATH_PROTOCOL associated with the DriverHandle, then this function will create a
		package of type EFI_PACKAGE_TYPE_DEVICE_PATH and add it to the package list.

우리는 이미 PackageList 배열을 채웠으므로 이 함수를 다음과 같이 사용할 수 있다.

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

이제 우리의 패키지 목록에 대한 EFI_HII_HANDLE Handle 이 있으므로 HII 데이터베이스에서 문자열을 가져오는 것을 시도해볼 차례이다.

이를 위해 다른 HII 데이터베이스 프로토콜인 EFI_HII_STRING_PROTOCOL의 GetString을 활용할 수 있다.

EFI_HII_STRING_PROTOCOL.GetString()

Summary:
Returns information about a string in a specific language, associated with a package list.

Prototype:
typedef
EFI_STATUS
(EFIAPI *EFI_HII_GET_STRING) (
 IN CONST EFI_HII_STRING_PROTOCOL *This,
 IN CONST CHAR8 *Language,
 IN EFI_HII_HANDLE PackageList,
 IN EFI_STRING_ID StringId,
 OUT EFI_STRING String,
 IN OUT UINTN *StringSize,
 OUT EFI_FONT_INFO **StringFontInfo OPTIONAL
 );
 
Parameters:
This			A pointer to the EFI_HII_STRING_PROTOCOL instance.
PackageList		The package list in the HII database to search for the specified string.
Language		Points to the language for the retrieved string. Callers of interfaces that require RFC
				4646 language codes to retrieve a Unicode string must use the RFC 4647 algorithm to
				lookup the Unicode string with the closest matching RFC 4646 language code.
StringId		The string’s id, which is unique within PackageList.
String			Points to the new null-terminated string.
StringSize		On entry, points to the size of the buffer pointed to by String, in bytes. On return,
				points to the length of the string, in bytes.
StringFontInfo	Points to a buffer that will be callee allocated and will have the string's font
				information into this buffer. The caller is responsible for freeing this buffer. If the
				parameter is NULL a buffer will not be allocated and the string font information will
				not be returned.

Description:
This function retrieves the string specified by StringId which is associated with the specified
PackageList in the language Language and copies it into the buffer specified by String.

다시 한번 설명하지만 알 수 없는 크기의 리소스를 가져올 때 사용하는 표준 UEFI체계가 있다.

먼저 StringSize=0으로 GetString()을 호출한다. 이 함수는 EFI_BUFFER_TOO_SMALL을 반환하지만 필요한 값으로 StringSize를 채우게 된다. 그런 다음 이번에는 올바른 StringSize를 사용하여 GetString을 한 번 더 호출한다.

우리의 애플리케이션에 UefiHiiServicesLib를 포함했기 때문에 EFI_HII_STRING_PROTOCOL을 찾기 위해 LocateProtocol을 수행할 필요가 없으며 대신 단순히 gHiiString 변수를 사용할 수 있다.

다음은 단순히 (ld, Language)조합을 제공하여 EFI_HII_HANDLE을 이용해 패키지 목록에서 문자열을 출력하기 위한 PrintStringFromHiiHandle 함수이다.

EFI_STATUS PrintStringFromHiiHandle(EFI_HII_HANDLE* Handle, CHAR8* Language, UINTN StringId)
{
  EFI_STRING String = NULL;
  UINTN StringSize = 0;
  EFI_STATUS Status = gHiiString->GetString(gHiiString, Language, *Handle, StringId, String, &StringSize, NULL);

  if (Status != EFI_BUFFER_TOO_SMALL) {
    return Status;
  }

  String = AllocateZeroPool(StringSize);
  if (String == NULL) {
    return Status;
  }

  Status = gHiiString->GetString(gHiiString, Language, *Handle, StringId, String, &StringSize, NULL);

  Print(L"Status = %r, %s\n", Status, String);

  FreePool(String);

  return EFI_SUCCESS;
}

우리의 패키지를 등록한 후에는 다음과 같이 사용할 수 있다.

  PrintStringFromHiiHandle(&Handle, "en-US", 1);
  PrintStringFromHiiHandle(&Handle, "en-US", 2);
  PrintStringFromHiiHandle(&Handle, "fr-FR", 1);
  PrintStringFromHiiHandle(&Handle, "fr-FR", 2);

이제 모든 것을 결합하고 우리의 앱을 빌드하고 OVMF에서 실행시키면 다음과 같은 값을 얻을 수 있다.

FS0:\> HIIStringsC.efi
Status = Success, English
Status = Success, Hello
Status = Success, French
Status = Success, Bonjour

우리가 만들었던 ShowHII 애플리케이션을 실행시키면 패키지가 추가된 것을 볼 수도 있다.

FS0:\> ShowHII.efi
...
PackageList[20]: GUID=8E0B8ED3-14F7-499D-A224-AEE89DC97FA3; size=0xC0
        Package[0]: type=STRINGS; size=0x53
        Package[1]: type=STRINGS; size=0x55
        Package[2]: type=END; size=0x4

HIIStringsC 애플리케이션을 다시 실행시키면 오류가 발생하는 것을 알아챌 수 있다.

FS0:\> HIIStringsC.efi
Can't register HII Package list 8E0B8ED3-14F7-499D-A224-AEE89DC97FA3, status = Invalid Parameter

이 오류는 동일한 GUID로 두 개의 패키지 목록을 등록할 수 없기 때문에 발생한다.

Previous46. EFI_HII_DATABASE_PROTOCOL의 NewPackageList를 사용하여 문자열 패키지가 포함된 HII 패키지 목록 게시Next48. UNI 파일 및 HiiLib를 사용하여 HII String 패키지 게시 및 작업하기

Last updated 2 years ago

🖥️