Trawling

Kevin Boone, Linux C 프로그램을 UEFI로 부팅하는 5부 안내서 공개

Kevin Boone은 Linux에서 작성한 C 프로그램을 UEFI로 부팅하는 5부 안내서와 `efitest` 예제를 공개했습니다. GCC와 gnu-efi로 PE32+ 실행 파일을 만들고 부팅 매체에서 실행한 뒤 Simple File Protocol로 파일에 접근하는 과정을 설명합니다.

Kevin Boone은 2026년 10월 12일 자신의 웹사이트에 Linux에서 작성한 C 프로그램을 UEFI 펌웨어로 부팅하는 5부 안내서를 게시했습니다. 관련 공개 GitHub 저장소에는 키보드 입력을 읽어 콘솔에 그대로 출력하는 efitest 예제와 Makefile, 부팅용 ISO 이미지가 있습니다. 안내서는 Linux와 C 빌드 경험은 있지만 UEFI를 처음 접하는 독자를 대상으로 하며, 64비트 Intel·AMD PC를 다룹니다.

이 안내서에서 베어메탈 프로그램은 운영체제 대신 컴퓨터의 UEFI 펌웨어가 제공하는 최소 기능을 바탕으로 부팅 때 실행되는 프로그램을 뜻합니다. Linux는 코드를 작성하고 빌드하는 개발 환경이며, 완성된 프로그램은 Linux와 별개로 UEFI가 메모리에 올려 실행합니다. UEFI는 콘솔 출력과 메모리 관리, VFAT 파일 읽기 등을 제공하고, 그 밖의 기능은 프로그램 코드나 함께 연결한 EFI 호환 라이브러리가 맡습니다.

첫 단계는 Linux용 실행 파일과 UEFI용 실행 파일의 형식 차이를 처리하는 일입니다. Linux에서 GCC로 만든 C 코드는 ELF 오브젝트 파일이 되지만, UEFI가 실행할 파일은 PE32+ 형식이어야 합니다. Boone의 설명에서 gnu-efi 시작 코드는 실행 환경을 준비해 efi_main을 호출합니다. 아키텍처별 링크 스크립트와 라이브러리를 이용해 중간 공유 객체를 만들고, objcopy로 EFI 실행 파일을 출력합니다. 이 과정은 CPU 명령어 자체보다 UEFI가 기대하는 파일 구조와 함수 호출 규약을 맞추는 데 초점이 있습니다. GCC의 함수 호출 규약이 EFI와 다를 수 있어 gnu-efi의 uefi_call_wrapper가 필요한 경우 인자 전달을 조정합니다.

UEFI 프로그램에는 Linux에서 쓰는 C 표준 라이브러리가 기본으로 들어 있지 않습니다. 따라서 printf나 fopen 같은 함수는 직접 구현하거나 EFI 호환 라이브러리를 연결해야 사용할 수 있습니다. EFI 인터페이스가 쓰는 문자열은 16비트 형식이므로 안내서는 GCC의 -fshort-wchar 설정을 설명합니다. EFI에 전달할 정수에는 UINTN 같은 EFI 자료형을 쓰며, 파일 경로 구분자로는 백슬래시를 사용합니다.

하드디스크에서 실행하는 실습은 VFAT으로 포맷한 EFI 시스템 파티션(ESP)에 x64 실행 파일을 EFI/BOOT/BOOTX64.EFI라는 경로로 복사합니다. Boone의 절차는 첫 파티션에 ESP를 만들고, 컴퓨터를 켤 때 부팅 메뉴에서 해당 드라이브를 선택하는 방식입니다. 가상 머신에 시험용 디스크를 추가해 실습하는 방법도 안내합니다. 새 파티션 테이블을 쓰는 과정에서 선택한 드라이브의 기존 데이터가 덮어써질 수 있기 때문입니다.

이동식 매체로 시험할 때는 일반적인 DVD의 ISO9660 형식과 EFI 부팅에 쓰는 VFAT 파티션을 연결해야 합니다. 예제는 El Torito 부팅 카탈로그를 이용해 VFAT 파일시스템을 담은 플로피 이미지 파일을 ISO에 넣습니다. UEFI는 이 이미지를 부팅용 플로피처럼 읽어 그 안의 EFI 실행 파일을 시작합니다. ISO를 VirtualBox의 가상 DVD로 연결해 시험하거나, 같은 이미지를 USB 장치에 dd로 기록해 실제 PC에서 부팅할 수 있습니다. Boone은 VirtualBox와 실제 PC에서 Secure Boot를 꺼야 한다고 안내합니다. dd로 이미지를 기록하면 대상 USB 장치의 기존 데이터가 덮어써집니다.

5부는 프로그램이 파일에 접근하는 과정을 설명합니다. efi_main이 받는 이미지 핸들은 메모리에 올라온 프로그램을 가리킵니다. 프로그램은 Loaded Image Protocol을 이용해 실행 파일이 있던 장치의 핸들을 얻고, 그 장치에서 Simple File Protocol을 찾습니다. 이 프로토콜의 OpenVolume 호출은 해당 볼륨의 루트 디렉터리를 돌려줍니다. 프로그램은 이 루트를 기준으로 파일을 열어 읽거나 씁니다. 각 볼륨은 자체 루트를 가진 채 독립적으로 처리되며, Linux처럼 여러 볼륨을 하나의 디렉터리 트리에 합치는 마운트 기능은 제공되지 않습니다. 안내서는 주로 VFAT을 다루며, 다른 파일시스템을 사용하려면 블록 장치 단계에서 필요한 처리를 구현해야 한다고 설명합니다.

Boone은 EFI 환경에서 일반적인 디버깅·프로파일링 도구를 쓰기 어렵다고 설명하며, 연결 목록이나 문자열 처리처럼 플랫폼에 덜 의존하는 코드는 Linux에서 따로 시험하는 방법을 제안합니다. 저장소의 빌드 절차에는 64비트 Linux와 gnu-efi 개발 파일, 플로피 이미지 조작용 mtools, ISO 생성용 xorriso가 필요합니다. 실제 예제 프로그램은 키보드 입력을 콘솔에 되돌려 주는 작은 코드지만, 안내서는 C 소스를 EFI 실행 파일로 만들고 부팅 매체에 배치한 뒤 펌웨어로 실행하고 파일에 접근하는 과정을 이어서 보여줍니다.

참고 자료

오류 제보