Skip to content

Instantly share code, notes, and snippets.

@tomtzook
Created January 16, 2021 11:15
Show Gist options
  • Save tomtzook/6c93dfe4a3eb8f17aae04322a95f9c61 to your computer and use it in GitHub Desktop.
Save tomtzook/6c93dfe4a3eb8f17aae04322a95f9c61 to your computer and use it in GitHub Desktop.
Compiling C++ EFI application with CMake and GNU-EFI, and running in QEMU
cmake_minimum_required(VERSION 3.16.3)
project(cppefi C CXX)
if (NOT CMAKE_RUNTIME_OUTPUT_DIRECTORY)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin")
endif()
if (NOT CMAKE_LIBRARY_OUTPUT_DIRECTORY)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib")
endif()
set(CMAKE_C_COMPILER /usr/bin/gcc)
set(CMAKE_CXX_COMPILER /usr/bin/gcc)
set(CMAKE_LINKER /usr/bin/ld)
set(CMAKE_C_CREATE_SHARED_LIBRARY "<CMAKE_LINKER> <CMAKE_C_LINK_FLAGS> <LINK_FLAGS> <OBJECTS> -o <TARGET> <LINK_LIBRARIES>")
set(CMAKE_CXX_CREATE_SHARED_LIBRARY "<CMAKE_LINKER> <CMAKE_CXX_LINK_FLAGS> <LINK_FLAGS> <OBJECTS> -o <TARGET> <LINK_LIBRARIES>")
set(CMAKE_BUILD_TYPE Debug)
set(CMAKE_C_STANDARD 11)
set(CMAKE_CXX_STANDARD 14)
set(ARCH x86_64)
set(EFI_INCLUDE_PATH /usr/local/include/efi)
set(LIB_PATH /usr/local/lib)
set(EFI_LIB_PATH /usr/local/lib)
set(EFI_CRT_OBJS ${EFI_LIB_PATH}/crt0-efi-${ARCH}.o)
set(EFI_LDS ${EFI_LIB_PATH}/elf_${ARCH}_efi.lds)
list(APPEND COMPILE_FLAGS "-fno-stack-protector" "-fpic" "-fshort-wchar" "-mno-red-zone" "-Wall" "-DEFI_FUNCTION_WRAPPER")
set(LINK_FLAGS -nostdlib -T ${EFI_LDS} -shared -Bsymbolic -L ${EFI_LIB_PATH} -L ${LIB_PATH} ${EFI_CRT_OBJS})
include_directories(${EFI_INCLUDE_PATH} ${EFI_INCLUDE_PATH}/${ARCH} ${EFI_INCLUDE_PATH}/protocol)
set(TARGET_NAME cppefi)
add_library(${TARGET_NAME} SHARED main.cpp)
target_compile_options(${TARGET_NAME} PRIVATE ${COMPILE_FLAGS})
target_link_options(${TARGET_NAME} PRIVATE ${LINK_FLAGS})
target_link_libraries(${TARGET_NAME} PRIVATE efi gnuefi)
add_custom_command(TARGET "${TARGET_NAME}" POST_BUILD
COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_RUNTIME_OUTPUT_DIRECTORY})
function(efi_objcopy)
cmake_parse_arguments(parsedargs "" "INFILE;OUTFILE" "SECTIONS" ${ARGN})
add_custom_command(TARGET "${TARGET_NAME}" POST_BUILD
COMMAND ${CMAKE_OBJCOPY}
${parsedargs_SECTIONS}
--target=efi-app-x86_64 # "efi-app", "efi-bsd", "efi-rtd"
"${parsedargs_INFILE}"
"${parsedargs_OUTFILE}")
endfunction()
set(ELF_SECTIONS
-j .text
-j .sdata
-j .data
-j .dynamic
-j .dynsym
-j .rel
-j .rela
-j .reloc)
efi_objcopy(INFILE "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/lib${TARGET_NAME}.so"
OUTFILE "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TARGET_NAME}.efi"
SECTIONS ${ELF_SECTIONS})
extern "C" {
#include <efi.h>
#include <efilib.h>
}
extern "C"
EFI_STATUS EFIAPI
efi_main (EFI_HANDLE image_handle, EFI_SYSTEM_TABLE* system_table)
{
InitializeLib(image_handle, system_table);
Print((CHAR16*)L"Hello from the UEFI\n");
return EFI_SUCCESS;
}
#!/bin/bash
BUILD_PATH=build
RUN_PATH=build/qemu
OVMF_DISK_IMG=/usr/share/ovmf/OVMF.fd
BINARY_PATH=${BUILD_PATH}/bin/cppefi.efi
DISK_PATH=${RUN_PATH}/uefi.img
# clean previous
rm -rf ${BUILD_PATH}
# build
mkdir -p ${BUILD_PATH}
cd ${BUILD_PATH}
cmake ..
make
cd ..
# make image
mkdir -p ${RUN_PATH}
## prepare files for efi partition (application binary + startup script)
dd if=/dev/zero of=/tmp/part.img bs=512 count=91669
mformat -i /tmp/part.img -h 32 -t 32 -n 64 -c 1
mcopy -i /tmp/part.img ${BINARY_PATH} ::app.efi
echo app.efi > startup.nsh
mcopy -i /tmp/part.img startup.nsh ::/
## make full image (with format and efi partition)
dd if=/dev/zero of=${DISK_PATH} bs=512 count=93750
parted ${DISK_PATH} -s -a minimal mklabel gpt
parted ${DISK_PATH} -s -a minimal mkpart EFI FAT16 2048s 93716s
parted ${DISK_PATH} -s -a minimal toggle 1 boot
## copy files into the image
dd if=/tmp/part.img of=${DISK_PATH} bs=512 count=91669 seek=2048 conv=notrunc
# run
qemu-system-x86_64 \
-cpu qemu64 \
-enable-kvm \
-net none \
-drive if=pflash,format=raw,unit=0,file=${OVMF_DISK_IMG},readonly=on \
-drive if=ide,format=raw,file=${DISK_PATH}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment