💻
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. 부팅 옵션

19. bcfg 명령어를 사용한 부팅 옵션 수정

이번 장에서는 NVRAM 변수(BIOS 설정), 즉 부팅 사이에 지속되는 변수에 대해 설명한다.

이전에 OVMF 빌드로 생성된 파일이 있다.

$ ls -l Build/OvmfX64/RELEASE_GCC5/FV/OVMF*
-rw-rw-r-- 1 ubuntu ubuntu 3653632 11월 23 17:51 Build/OvmfX64/RELEASE_GCC5/FV/OVMF_CODE.fd
-rw-rw-r-- 1 ubuntu ubuntu 4194304 11월 24 10:23 Build/OvmfX64/RELEASE_GCC5/FV/OVMF.fd
-rw-rw-r-- 1 ubuntu ubuntu  540672 11월 23 21:10 Build/OvmfX64/RELEASE_GCC5/FV/OVMF_VARS.fd
  • OVMF_CODE.fd - code image (read-only)

  • OVMF_VARS.fd - NVRAM variables image (read-write)

  • OVMF.fd - combined image (OVMF_CODE.fd + OVMF_VARS.fd)

위 파일들을 이용해서 QEMU를 실행하는 2가지 방법이 있다.

OVMF.fd 파일 하나만 사용하는 방법

$ qemu-system-x86_64 -drive if=pflash,format=raw,file=Build/OvmfX64/RELEASE_GCC5/FV/OVMF.fd \
                     ...

OVMF_CODE.fd 와 OVMF_VARS.fd 를 사용한 방법

$ qemu-system-x86_64 -drive if=pflash,format=raw,readonly,file=Build/OvmfX64/RELEASE_GCC5/FV/OVMF_CODE.fd \
                     -drive if=pflash,format=raw,file=Build/OvmfX64/RELEASE_GCC5/FV/OVMF_VARS.fd \
                     ...

이전에는 짧게 OVMF.fd 파일만을 이용해서 진행했지만, 여기서는 NVRAM 변수를 수정할 것이기 때문에 초기 상태로 되돌릴 수 있도록OVMF_NVRAM.fd 파일을 복사하여 진행한다.

먼저 이전에 OVMF에 HelloWorld 애플리케이션을 넣었기 때문에 OVMF 패키지부터 초기 상태로 되돌린다.

$ git restore OvmfPkg
$ build --platform=OvmfPkg/OvmfPkgX64.dsc --arch=X64 --buildtarget=RELEASE --tagname=GCC5

OVMF를 초기 상태로 빌드하였기 때문에 이제 OVMF_VARS.fd를 복사한 후 복사한 파일을 사용하여 QEMU를 실행한다.

$ cp Build/OvmfX64/RELEASE_GCC5/FV/OVMF_VARS.fd ../
$ qemu-system-x86_64 -drive if=pflash,format=raw,readonly,file=Build/OvmfX64/RELEASE_GCC5/FV/OVMF_CODE.fd \
                     -drive if=pflash,format=raw,file=../OVMF_VARS.fd \
                     -drive format=raw,file=fat:rw:~/UEFI_disk \
                     -nographic \
                     -net none

부팅 변수를 변경하기 전에 bcfg boot dump 명령어를 통해 확인한다.

Shell> bcfg boot dump
Option: 00. Variable: Boot0000
  Desc    - UiApp
  DevPath - Fv(7CB8BDC9-F8EB-4F34-AAEA-3EE4AF6516A1)/FvFile(462CAA21-7614-4503-836E-8AB6F4662331)
  OVMF_VARS.fdiOptional- N
Option: 01. Variable: Boot0001
  Desc    - UEFI QEMU DVD-ROM QM00003
  DevPath - PciRoot(0x0)/Pci(0x1,0x1)/Ata(0x0)
  Optional- Y
Option: 02. Variable: Boot0002
  Desc    - UEFI QEMU HARDDISK QM00001
  DevPath - PciRoot(0x0)/Pci(0x1,0x1)/Ata(0x0)
  Optional- Y
Option: 03. Variable: Boot0003
  Desc    - EFI Internal Shell
  DevPath - Fv(7CB8BDC9-F8EB-4F34-AAEA-3EE4AF6516A1)/FvFile(7C04A583-9E3E-4F1C-AD65-E05268D0B4D1)
  Optional- N

부팅 옵션을 표시하는 것 외에도 bcfg 명령은 부팅 옵션을 추가/제거하거나 순서를 변경할 수 있다.

도움말은 아래 명령을 통해 확인할 수 있다.

bcfg -? -b

이제 부팅 옵션에 Interactive.efi 를 추가한다.

Shell> fs0:
FS0:\> bcfg boot add 4 InteractiveApp.efi "Interactive app"
Target = 0004.
bcfg: Add Boot0004 as 4

정상적으로 추가됐는지 확인하기 위해 다시 부팅 옵션을 확인한다.

FS0:\> bcfg boot dump
Option: 00. Variable: Boot0000
  Desc    - UiApp
  DevPath - Fv(7CB8BDC9-F8EB-4F34-AAEA-3EE4AF6516A1)/FvFile(462CAA21-7614-4503-836E-8AB6F4662331)
  Optional- N
Option: 01. Variable: Boot0001
  Desc    - UEFI QEMU DVD-ROM QM00003
  DevPath - PciRoot(0x0)/Pci(0x1,0x1)/Ata(0x0)
  Optional- Y
Option: 02. Variable: Boot0002
  Desc    - UEFI QEMU HARDDISK QM00001
  DevPath - PciRoot(0x0)/Pci(0x1,0x1)/Ata(0x0)
  Optional- Y
Option: 03. Variable: Boot0003
  Desc    - EFI Internal Shell
  DevPath - Fv(7CB8BDC9-F8EB-4F34-AAEA-3EE4AF6516A1)/FvFile(7C04A583-9E3E-4F1C-AD65-E05268D0B4D1)
  Optional- N
Option: 04. Variable: Boot0004
  Desc    - Interactive app
  DevPath - PciRoot(0x0)/Pci(0x1,0x1)/Ata(0x0)/HD(1,MBR,0xBE1AFDFA,0x3F,0xFBFC1)/\InteractiveApp.efi
  Optional- N

부팅 옵션을 확인했을 때도 추가가 된 것을 볼 수 있었고 부팅 매니저를 통해서도 확인이 가능하다.

해당 부팅 옵션은 OVMF_VARS.fd를 변경하지 않으면 QEMU를 다시 시작해도 계속해서 나타난다.

애플리케이션을 첫 번째 부팅 소스로 설정하는 것도 가능하다.

Shell> bcfg boot mv 4 0

다시 부팅 옵션을 확인하면 맨 아래에 있었던 Interactive app이 맨 위로 옮겨진 것을 볼 수 있다.

Shell> bcfg boot dump
Option: 00. Variable: Boot0004
  Desc    - Interactive app
  DevPath - PciRoot(0x0)/Pci(0x1,0x1)/Ata(0x0)/HD(1,MBR,0xBE1AFDFA,0x3F,0xFBFC1)/\InteractiveApp.efi
  Optional- N
Option: 01. Variable: Boot0000
  Desc    - UiApp
  DevPath - Fv(7CB8BDC9-F8EB-4F34-AAEA-3EE4AF6516A1)/FvFile(462CAA21-7614-4503-836E-8AB6F4662331)
  Optional- N
Option: 02. Variable: Boot0001
  Desc    - UEFI QEMU DVD-ROM QM00003
  DevPath - PciRoot(0x0)/Pci(0x1,0x1)/Ata(0x0)
  Optional- Y
Option: 03. Variable: Boot0002
  Desc    - UEFI QEMU HARDDISK QM00001
  DevPath - PciRoot(0x0)/Pci(0x1,0x1)/Ata(0x0)
  Optional- Y
Option: 04. Variable: Boot0003
  Desc    - EFI Internal Shell
  DevPath - Fv(7CB8BDC9-F8EB-4F34-AAEA-3EE4AF6516A1)/FvFile(7C04A583-9E3E-4F1C-AD65-E05268D0B4D1)
  Optional- N

EFI Internal Shell을 통해 reset 명령을 입력하여 재부팅 되면 Interactive app을 먼저 통과한 후 BIOS로 진입하는 모습을 볼 수 있다.

EFI Internal Shell을 통해 해당 부팅 옵션을 삭제할 수도 있다.

Shell> bcfg boot rm 0
Shell> bcfg boot dump
Option: 00. Variable: Boot0004
  Desc    - Interactive app
  DevPath - PciRoot(0x0)/Pci(0x1,0x1)/Ata(0x0)/HD(1,MBR,0xBE1AFDFA,0x3F,0xFBFC1)/\InteractiveApp.efi
  Optional- N
Option: 01. Variable: Boot0000
  Desc    - UiApp
  DevPath - Fv(7CB8BDC9-F8EB-4F34-AAEA-3EE4AF6516A1)/FvFile(462CAA21-7614-4503-836E-8AB6F4662331)
  Optional- N
Option: 02. Variable: Boot0001
  Desc    - UEFI QEMU DVD-ROM QM00003
  DevPath - PciRoot(0x0)/Pci(0x1,0x1)/Ata(0x0)
  Optional- Y
Option: 03. Variable: Boot0002
  Desc    - UEFI QEMU HARDDISK QM00001
  DevPath - PciRoot(0x0)/Pci(0x1,0x1)/Ata(0x0)
  Optional- Y
Option: 04. Variable: Boot0003
  Desc    - EFI Internal Shell
  DevPath - Fv(7CB8BDC9-F8EB-4F34-AAEA-3EE4AF6516A1)/FvFile(7C04A583-9E3E-4F1C-AD65-E05268D0B4D1)
  Optional- N

Shell> bcfg boot rm 0

Shell> bcfg boot dump
Option: 00. Variable: Boot0000
  Desc    - UiApp
  DevPath - Fv(7CB8BDC9-F8EB-4F34-AAEA-3EE4AF6516A1)/FvFile(462CAA21-7614-4503-836E-8AB6F4662331)
  Optional- N
Option: 01. Variable: Boot0001
  Desc    - UEFI QEMU DVD-ROM QM00003
  DevPath - PciRoot(0x0)/Pci(0x1,0x1)/Ata(0x0)
  Optional- Y
Option: 02. Variable: Boot0002
  Desc    - UEFI QEMU HARDDISK QM00001
  DevPath - PciRoot(0x0)/Pci(0x1,0x1)/Ata(0x0)
  Optional- Y
Option: 03. Variable: Boot0003
  Desc    - EFI Internal Shell
  DevPath - Fv(7CB8BDC9-F8EB-4F34-AAEA-3EE4AF6516A1)/FvFile(7C04A583-9E3E-4F1C-AD65-E05268D0B4D1)
  Optional- N
Previous18. ReadKeyStroke 함수로 사용자 입력 처리NextPCD

Last updated 2 years ago

🖥️
Boot Manager에 추가된 화면
Interactive app이 가장 먼저 실행