├── .gitattributes ├── .github └── workflows │ └── build.yml ├── .gitignore ├── CMakeLists.txt ├── LICENSE ├── README.md ├── cmake.toml ├── cmkr.cmake └── src └── EfiCMake ├── Efi.hpp ├── ProcessorBind.hpp └── main.cpp /.gitattributes: -------------------------------------------------------------------------------- 1 | /**/CMakeLists.txt linguist-generated 2 | /**/cmkr.cmake linguist-vendored 3 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: CMake 2 | 3 | on: [push, pull_request] 4 | 5 | jobs: 6 | build: 7 | # Skip building pull requests from the same repository 8 | if: ${{ github.event_name == 'push' || (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository) }} 9 | runs-on: ${{ matrix.os }} 10 | strategy: 11 | fail-fast: false 12 | matrix: 13 | os: [windows-2019] 14 | env: 15 | BUILD_TYPE: Release 16 | steps: 17 | - name: Checkout 18 | uses: actions/checkout@v2 19 | 20 | - name: Build 21 | run: | 22 | cmake -B build -DCMAKE_BUILD_TYPE=${{ env.BUILD_TYPE }} 23 | cmake --build build --config ${{ env.BUILD_TYPE }} --parallel 24 | 25 | - name: Upload artifacts 26 | uses: actions/upload-artifact@v2 27 | with: 28 | name: ${{ github.event.repository.name }}-${{ github.sha }} 29 | path: build/Release/* 30 | 31 | - name: Compress artifacts 32 | uses: vimtor/action-zip@v1 33 | with: 34 | files: build/Release/* 35 | dest: ${{ github.event.repository.name }}-${{ github.sha }}.zip 36 | 37 | - name: Release 38 | uses: softprops/action-gh-release@v1 39 | if: ${{ startsWith(github.ref, 'refs/tags/') }} 40 | with: 41 | prerelease: ${{ !startsWith(github.ref, 'refs/tags/v') || contains(github.ref, '-pre') }} 42 | files: ${{ github.event.repository.name }}-${{ github.sha }}.zip 43 | env: 44 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 45 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | bin 2 | bin2 3 | compile_commands.json 4 | .clangd 5 | temp.* 6 | .vs 7 | .cache 8 | build*/ 9 | .idea/ 10 | cmake-build*/ 11 | CMakeLists.txt.user 12 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # This file is automatically generated from cmake.toml - DO NOT EDIT 2 | # See https://github.com/build-cpp/cmkr for more information 3 | 4 | cmake_minimum_required(VERSION 3.15) 5 | 6 | if(CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR) 7 | message(FATAL_ERROR "In-tree builds are not supported. Run CMake from a separate directory: cmake -B build") 8 | endif() 9 | 10 | # Regenerate CMakeLists.txt automatically in the root project 11 | set(CMKR_ROOT_PROJECT OFF) 12 | if(CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR) 13 | set(CMKR_ROOT_PROJECT ON) 14 | 15 | # Bootstrap cmkr 16 | include(cmkr.cmake OPTIONAL RESULT_VARIABLE CMKR_INCLUDE_RESULT) 17 | if(CMKR_INCLUDE_RESULT) 18 | cmkr() 19 | endif() 20 | 21 | # Enable folder support 22 | set_property(GLOBAL PROPERTY USE_FOLDERS ON) 23 | endif() 24 | 25 | # Create a configure-time dependency on cmake.toml to improve IDE support 26 | if(CMKR_ROOT_PROJECT) 27 | configure_file(cmake.toml cmake.toml COPYONLY) 28 | endif() 29 | 30 | set(CMAKE_CONFIGURATION_TYPES "Release" CACHE STRING "") 31 | set(CMAKE_EXE_LINKER_FLAGS_RELEASE "/DEBUG:FULL /INCREMENTAL:NO" CACHE STRING "") 32 | set(CMAKE_SHARED_LINKER_FLAGS_RELEASE "/DEBUG:FULL /INCREMENTAL:NO" CACHE STRING "") 33 | set(CMAKE_BUILD_TYPE "Release" CACHE STRING "") 34 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /GS- /EHs-") 35 | 36 | project(EfiCMake) 37 | 38 | set(CMAKE_EXECUTABLE_SUFFIX ".efi") 39 | 40 | include(FetchContent) 41 | 42 | message(STATUS "Fetching edk2...") 43 | FetchContent_Declare(edk2 44 | URL 45 | "https://github.com/tianocore/edk2/archive/refs/tags/edk2-stable202205.tar.gz" 46 | URL_HASH 47 | SHA256=E6CF93BAE78B30A10732B8AFB5CC438735DC9EC976AE65D12DAB041C18BB7987 48 | ) 49 | FetchContent_MakeAvailable(edk2) 50 | 51 | # Target edk2_headers 52 | set(CMKR_TARGET edk2_headers) 53 | set(edk2_headers_SOURCES "") 54 | 55 | set(CMKR_SOURCES ${edk2_headers_SOURCES}) 56 | add_library(edk2_headers INTERFACE) 57 | 58 | if(edk2_headers_SOURCES) 59 | target_sources(edk2_headers INTERFACE ${edk2_headers_SOURCES}) 60 | endif() 61 | 62 | add_library(edk2::headers ALIAS edk2_headers) 63 | target_compile_features(edk2_headers INTERFACE 64 | cxx_std_17 65 | ) 66 | 67 | target_include_directories(edk2_headers INTERFACE 68 | "${edk2_SOURCE_DIR}/MdePkg/Include" 69 | "${edk2_SOURCE_DIR}/MdePkg/Include/X64" 70 | ) 71 | 72 | if(MSVC) # msvc 73 | target_link_options(edk2_headers INTERFACE 74 | "/NODEFAULTLIB" 75 | "/ENTRY:EfiEntry" 76 | "/SUBSYSTEM:EFI_APPLICATION" 77 | "/MANIFESTUAC:NO" 78 | "/DYNAMICBASE:NO" 79 | "/NXCOMPAT:NO" 80 | ) 81 | endif() 82 | 83 | unset(CMKR_TARGET) 84 | unset(CMKR_SOURCES) 85 | 86 | # Target EfiCMake 87 | set(CMKR_TARGET EfiCMake) 88 | set(EfiCMake_SOURCES "") 89 | 90 | list(APPEND EfiCMake_SOURCES 91 | "src/EfiCMake/main.cpp" 92 | "src/EfiCMake/Efi.hpp" 93 | "src/EfiCMake/ProcessorBind.hpp" 94 | ) 95 | 96 | list(APPEND EfiCMake_SOURCES 97 | cmake.toml 98 | ) 99 | 100 | set(CMKR_SOURCES ${EfiCMake_SOURCES}) 101 | add_executable(EfiCMake) 102 | 103 | if(EfiCMake_SOURCES) 104 | target_sources(EfiCMake PRIVATE ${EfiCMake_SOURCES}) 105 | endif() 106 | 107 | get_directory_property(CMKR_VS_STARTUP_PROJECT DIRECTORY ${PROJECT_SOURCE_DIR} DEFINITION VS_STARTUP_PROJECT) 108 | if(NOT CMKR_VS_STARTUP_PROJECT) 109 | set_property(DIRECTORY ${PROJECT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT EfiCMake) 110 | endif() 111 | 112 | source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} FILES ${EfiCMake_SOURCES}) 113 | 114 | target_link_libraries(EfiCMake PRIVATE 115 | edk2::headers 116 | ) 117 | 118 | unset(CMKR_TARGET) 119 | unset(CMKR_SOURCES) 120 | 121 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Boost Software License - Version 1.0 - August 17th, 2003 2 | 3 | Permission is hereby granted, free of charge, to any person or organization 4 | obtaining a copy of the software and accompanying documentation covered by 5 | this license (the "Software") to use, reproduce, display, distribute, 6 | execute, and transmit the Software, and to prepare derivative works of the 7 | Software, and to permit third-parties to whom the Software is furnished to 8 | do so, all subject to the following: 9 | 10 | The copyright notices in the Software and this entire statement, including 11 | the above license grant, this restriction and the following disclaimer, 12 | must be included in all copies of the Software, in whole or in part, and 13 | all derivative works of the Software, unless such copies or derivative 14 | works are solely in the form of machine-executable object code generated by 15 | a source language processor. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT 20 | SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE 21 | FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, 22 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 23 | DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # EfiCMake 2 | 3 | CMake template for a basic EFI application/bootkit. 4 | 5 | ![screenshot](https://i.imgur.com/0WhUFqM.png) 6 | 7 | **Note**: This currently only links with the EDK2 headers. This means you will not be able to use global variables like `gST` or EDK2 functions like `Print`. 8 | 9 | ## Building (Visual Studio) 10 | 11 | This is only tested on Windows with Visual Studio. 12 | 13 | - Configure the project with `cmake -B build` 14 | - Open `build\EfiCMake.sln` and build the solution 15 | - `EfiCMake.efi` will be in the `build\Release` folder 16 | -------------------------------------------------------------------------------- /cmake.toml: -------------------------------------------------------------------------------- 1 | # Reference: https://build-cpp.github.io/cmkr/cmake-toml 2 | [project] 3 | name = "EfiCMake" 4 | cmake-before = """ 5 | set(CMAKE_CONFIGURATION_TYPES "Release" CACHE STRING "") 6 | set(CMAKE_EXE_LINKER_FLAGS_RELEASE "/DEBUG:FULL /INCREMENTAL:NO" CACHE STRING "") 7 | set(CMAKE_SHARED_LINKER_FLAGS_RELEASE "/DEBUG:FULL /INCREMENTAL:NO" CACHE STRING "") 8 | set(CMAKE_BUILD_TYPE "Release" CACHE STRING "") 9 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /GS- /EHs-") 10 | """ 11 | cmake-after = """ 12 | set(CMAKE_EXECUTABLE_SUFFIX ".efi") 13 | """ 14 | 15 | [fetch-content.edk2] 16 | url = "https://github.com/tianocore/edk2/archive/refs/tags/edk2-stable202205.tar.gz" 17 | sha256 = "E6CF93BAE78B30A10732B8AFB5CC438735DC9EC976AE65D12DAB041C18BB7987" 18 | 19 | # Hacky thing just for the bootkit 20 | [target.edk2_headers] 21 | alias = "edk2::headers" 22 | type = "interface" 23 | include-directories = [ 24 | "${edk2_SOURCE_DIR}/MdePkg/Include", 25 | "${edk2_SOURCE_DIR}/MdePkg/Include/X64", 26 | ] 27 | msvc.link-options = [ 28 | "/NODEFAULTLIB", 29 | "/ENTRY:EfiEntry", 30 | "/SUBSYSTEM:EFI_APPLICATION", 31 | "/MANIFESTUAC:NO", 32 | "/DYNAMICBASE:NO", 33 | "/NXCOMPAT:NO", 34 | ] 35 | compile-features = ["cxx_std_17"] 36 | 37 | [target.EfiCMake] 38 | type = "executable" 39 | sources = ["src/EfiCMake/*.cpp", "src/EfiCMake/*.hpp"] 40 | link-libraries = ["edk2::headers"] 41 | -------------------------------------------------------------------------------- /cmkr.cmake: -------------------------------------------------------------------------------- 1 | include_guard() 2 | 3 | # Change these defaults to point to your infrastructure if desired 4 | set(CMKR_REPO "https://github.com/build-cpp/cmkr" CACHE STRING "cmkr git repository" FORCE) 5 | set(CMKR_TAG "v0.2.13" CACHE STRING "cmkr git tag (this needs to be available forever)" FORCE) 6 | set(CMKR_COMMIT_HASH "" CACHE STRING "cmkr git commit hash (optional)" FORCE) 7 | 8 | # To bootstrap/generate a cmkr project: cmake -P cmkr.cmake 9 | if(CMAKE_SCRIPT_MODE_FILE) 10 | set(CMAKE_BINARY_DIR "${CMAKE_BINARY_DIR}/build") 11 | set(CMAKE_CURRENT_BINARY_DIR "${CMAKE_BINARY_DIR}") 12 | file(MAKE_DIRECTORY "${CMAKE_BINARY_DIR}") 13 | endif() 14 | 15 | # Set these from the command line to customize for development/debugging purposes 16 | set(CMKR_EXECUTABLE "" CACHE FILEPATH "cmkr executable") 17 | set(CMKR_SKIP_GENERATION OFF CACHE BOOL "skip automatic cmkr generation") 18 | set(CMKR_BUILD_TYPE "Debug" CACHE STRING "cmkr build configuration") 19 | mark_as_advanced(CMKR_REPO CMKR_TAG CMKR_COMMIT_HASH CMKR_EXECUTABLE CMKR_SKIP_GENERATION CMKR_BUILD_TYPE) 20 | 21 | # Disable cmkr if generation is disabled 22 | if(DEFINED ENV{CI} OR CMKR_SKIP_GENERATION OR CMKR_BUILD_SKIP_GENERATION) 23 | message(STATUS "[cmkr] Skipping automatic cmkr generation") 24 | unset(CMKR_BUILD_SKIP_GENERATION CACHE) 25 | macro(cmkr) 26 | endmacro() 27 | return() 28 | endif() 29 | 30 | # Disable cmkr if no cmake.toml file is found 31 | if(NOT CMAKE_SCRIPT_MODE_FILE AND NOT EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/cmake.toml") 32 | message(AUTHOR_WARNING "[cmkr] Not found: ${CMAKE_CURRENT_SOURCE_DIR}/cmake.toml") 33 | macro(cmkr) 34 | endmacro() 35 | return() 36 | endif() 37 | 38 | # Convert a Windows native path to CMake path 39 | if(CMKR_EXECUTABLE MATCHES "\\\\") 40 | string(REPLACE "\\" "/" CMKR_EXECUTABLE_CMAKE "${CMKR_EXECUTABLE}") 41 | set(CMKR_EXECUTABLE "${CMKR_EXECUTABLE_CMAKE}" CACHE FILEPATH "" FORCE) 42 | unset(CMKR_EXECUTABLE_CMAKE) 43 | endif() 44 | 45 | # Helper macro to execute a process (COMMAND_ERROR_IS_FATAL ANY is 3.19 and higher) 46 | function(cmkr_exec) 47 | execute_process(COMMAND ${ARGV} RESULT_VARIABLE CMKR_EXEC_RESULT) 48 | if(NOT CMKR_EXEC_RESULT EQUAL 0) 49 | message(FATAL_ERROR "cmkr_exec(${ARGV}) failed (exit code ${CMKR_EXEC_RESULT})") 50 | endif() 51 | endfunction() 52 | 53 | # Windows-specific hack (CMAKE_EXECUTABLE_PREFIX is not set at the moment) 54 | if(WIN32) 55 | set(CMKR_EXECUTABLE_NAME "cmkr.exe") 56 | else() 57 | set(CMKR_EXECUTABLE_NAME "cmkr") 58 | endif() 59 | 60 | # Use cached cmkr if found 61 | if(DEFINED ENV{CMKR_CACHE} AND EXISTS "$ENV{CMKR_CACHE}") 62 | set(CMKR_DIRECTORY_PREFIX "$ENV{CMKR_CACHE}") 63 | string(REPLACE "\\" "/" CMKR_DIRECTORY_PREFIX "${CMKR_DIRECTORY_PREFIX}") 64 | if(NOT CMKR_DIRECTORY_PREFIX MATCHES "\\/$") 65 | set(CMKR_DIRECTORY_PREFIX "${CMKR_DIRECTORY_PREFIX}/") 66 | endif() 67 | # Build in release mode for the cache 68 | set(CMKR_BUILD_TYPE "Release") 69 | else() 70 | set(CMKR_DIRECTORY_PREFIX "${CMAKE_CURRENT_BINARY_DIR}/_cmkr_") 71 | endif() 72 | set(CMKR_DIRECTORY "${CMKR_DIRECTORY_PREFIX}${CMKR_TAG}") 73 | set(CMKR_CACHED_EXECUTABLE "${CMKR_DIRECTORY}/bin/${CMKR_EXECUTABLE_NAME}") 74 | 75 | # Handle upgrading logic 76 | if(CMKR_EXECUTABLE AND NOT CMKR_CACHED_EXECUTABLE STREQUAL CMKR_EXECUTABLE) 77 | if(CMKR_EXECUTABLE MATCHES "^${CMAKE_CURRENT_BINARY_DIR}/_cmkr") 78 | if(DEFINED ENV{CMKR_CACHE} AND EXISTS "$ENV{CMKR_CACHE}") 79 | message(AUTHOR_WARNING "[cmkr] Switching to cached cmkr: '${CMKR_CACHED_EXECUTABLE}'") 80 | if(EXISTS "${CMKR_CACHED_EXECUTABLE}") 81 | set(CMKR_EXECUTABLE "${CMKR_CACHED_EXECUTABLE}" CACHE FILEPATH "Full path to cmkr executable" FORCE) 82 | else() 83 | unset(CMKR_EXECUTABLE CACHE) 84 | endif() 85 | else() 86 | message(AUTHOR_WARNING "[cmkr] Upgrading '${CMKR_EXECUTABLE}' to '${CMKR_CACHED_EXECUTABLE}'") 87 | unset(CMKR_EXECUTABLE CACHE) 88 | endif() 89 | elseif(DEFINED ENV{CMKR_CACHE} AND EXISTS "$ENV{CMKR_CACHE}" AND CMKR_EXECUTABLE MATCHES "^${CMKR_DIRECTORY_PREFIX}") 90 | message(AUTHOR_WARNING "[cmkr] Upgrading cached '${CMKR_EXECUTABLE}' to '${CMKR_CACHED_EXECUTABLE}'") 91 | unset(CMKR_EXECUTABLE CACHE) 92 | endif() 93 | endif() 94 | 95 | if(CMKR_EXECUTABLE AND EXISTS "${CMKR_EXECUTABLE}") 96 | message(VERBOSE "[cmkr] Found cmkr: '${CMKR_EXECUTABLE}'") 97 | elseif(CMKR_EXECUTABLE AND NOT CMKR_EXECUTABLE STREQUAL CMKR_CACHED_EXECUTABLE) 98 | message(FATAL_ERROR "[cmkr] '${CMKR_EXECUTABLE}' not found") 99 | elseif(NOT CMKR_EXECUTABLE AND EXISTS "${CMKR_CACHED_EXECUTABLE}") 100 | set(CMKR_EXECUTABLE "${CMKR_CACHED_EXECUTABLE}" CACHE FILEPATH "Full path to cmkr executable" FORCE) 101 | message(STATUS "[cmkr] Found cached cmkr: '${CMKR_EXECUTABLE}'") 102 | else() 103 | set(CMKR_EXECUTABLE "${CMKR_CACHED_EXECUTABLE}" CACHE FILEPATH "Full path to cmkr executable" FORCE) 104 | message(VERBOSE "[cmkr] Bootstrapping '${CMKR_EXECUTABLE}'") 105 | 106 | message(STATUS "[cmkr] Fetching cmkr...") 107 | if(EXISTS "${CMKR_DIRECTORY}") 108 | cmkr_exec("${CMAKE_COMMAND}" -E rm -rf "${CMKR_DIRECTORY}") 109 | endif() 110 | find_package(Git QUIET REQUIRED) 111 | cmkr_exec("${GIT_EXECUTABLE}" 112 | clone 113 | --config advice.detachedHead=false 114 | --branch ${CMKR_TAG} 115 | --depth 1 116 | ${CMKR_REPO} 117 | "${CMKR_DIRECTORY}" 118 | ) 119 | if(CMKR_COMMIT_HASH) 120 | execute_process( 121 | COMMAND "${GIT_EXECUTABLE}" checkout -q "${CMKR_COMMIT_HASH}" 122 | RESULT_VARIABLE CMKR_EXEC_RESULT 123 | WORKING_DIRECTORY "${CMKR_DIRECTORY}" 124 | ) 125 | if(NOT CMKR_EXEC_RESULT EQUAL 0) 126 | message(FATAL_ERROR "Tag '${CMKR_TAG}' hash is not '${CMKR_COMMIT_HASH}'") 127 | endif() 128 | endif() 129 | message(STATUS "[cmkr] Building cmkr (using system compiler)...") 130 | cmkr_exec("${CMAKE_COMMAND}" 131 | --no-warn-unused-cli 132 | "${CMKR_DIRECTORY}" 133 | "-B${CMKR_DIRECTORY}/build" 134 | "-DCMAKE_BUILD_TYPE=${CMKR_BUILD_TYPE}" 135 | "-DCMAKE_UNITY_BUILD=ON" 136 | "-DCMAKE_INSTALL_PREFIX=${CMKR_DIRECTORY}" 137 | "-DCMKR_GENERATE_DOCUMENTATION=OFF" 138 | ) 139 | cmkr_exec("${CMAKE_COMMAND}" 140 | --build "${CMKR_DIRECTORY}/build" 141 | --config "${CMKR_BUILD_TYPE}" 142 | --parallel 143 | ) 144 | cmkr_exec("${CMAKE_COMMAND}" 145 | --install "${CMKR_DIRECTORY}/build" 146 | --config "${CMKR_BUILD_TYPE}" 147 | --prefix "${CMKR_DIRECTORY}" 148 | --component cmkr 149 | ) 150 | if(NOT EXISTS ${CMKR_EXECUTABLE}) 151 | message(FATAL_ERROR "[cmkr] Failed to bootstrap '${CMKR_EXECUTABLE}'") 152 | endif() 153 | cmkr_exec("${CMKR_EXECUTABLE}" version) 154 | message(STATUS "[cmkr] Bootstrapped ${CMKR_EXECUTABLE}") 155 | endif() 156 | execute_process(COMMAND "${CMKR_EXECUTABLE}" version 157 | RESULT_VARIABLE CMKR_EXEC_RESULT 158 | ) 159 | if(NOT CMKR_EXEC_RESULT EQUAL 0) 160 | message(FATAL_ERROR "[cmkr] Failed to get version, try clearing the cache and rebuilding") 161 | endif() 162 | 163 | # Use cmkr.cmake as a script 164 | if(CMAKE_SCRIPT_MODE_FILE) 165 | if(NOT EXISTS "${CMAKE_SOURCE_DIR}/cmake.toml") 166 | execute_process(COMMAND "${CMKR_EXECUTABLE}" init 167 | RESULT_VARIABLE CMKR_EXEC_RESULT 168 | ) 169 | if(NOT CMKR_EXEC_RESULT EQUAL 0) 170 | message(FATAL_ERROR "[cmkr] Failed to bootstrap cmkr project. Please report an issue: https://github.com/build-cpp/cmkr/issues/new") 171 | else() 172 | message(STATUS "[cmkr] Modify cmake.toml and then configure using: cmake -B build") 173 | endif() 174 | else() 175 | execute_process(COMMAND "${CMKR_EXECUTABLE}" gen 176 | RESULT_VARIABLE CMKR_EXEC_RESULT 177 | ) 178 | if(NOT CMKR_EXEC_RESULT EQUAL 0) 179 | message(FATAL_ERROR "[cmkr] Failed to generate project.") 180 | else() 181 | message(STATUS "[cmkr] Configure using: cmake -B build") 182 | endif() 183 | endif() 184 | endif() 185 | 186 | # This is the macro that contains black magic 187 | macro(cmkr) 188 | # When this macro is called from the generated file, fake some internal CMake variables 189 | get_source_file_property(CMKR_CURRENT_LIST_FILE "${CMAKE_CURRENT_LIST_FILE}" CMKR_CURRENT_LIST_FILE) 190 | if(CMKR_CURRENT_LIST_FILE) 191 | set(CMAKE_CURRENT_LIST_FILE "${CMKR_CURRENT_LIST_FILE}") 192 | get_filename_component(CMAKE_CURRENT_LIST_DIR "${CMAKE_CURRENT_LIST_FILE}" DIRECTORY) 193 | endif() 194 | 195 | # File-based include guard (include_guard is not documented to work) 196 | get_source_file_property(CMKR_INCLUDE_GUARD "${CMAKE_CURRENT_LIST_FILE}" CMKR_INCLUDE_GUARD) 197 | if(NOT CMKR_INCLUDE_GUARD) 198 | set_source_files_properties("${CMAKE_CURRENT_LIST_FILE}" PROPERTIES CMKR_INCLUDE_GUARD TRUE) 199 | 200 | file(SHA256 "${CMAKE_CURRENT_LIST_FILE}" CMKR_LIST_FILE_SHA256_PRE) 201 | 202 | # Generate CMakeLists.txt 203 | cmkr_exec("${CMKR_EXECUTABLE}" gen 204 | WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" 205 | ) 206 | 207 | file(SHA256 "${CMAKE_CURRENT_LIST_FILE}" CMKR_LIST_FILE_SHA256_POST) 208 | 209 | # Delete the temporary file if it was left for some reason 210 | set(CMKR_TEMP_FILE "${CMAKE_CURRENT_SOURCE_DIR}/CMakerLists.txt") 211 | if(EXISTS "${CMKR_TEMP_FILE}") 212 | file(REMOVE "${CMKR_TEMP_FILE}") 213 | endif() 214 | 215 | if(NOT CMKR_LIST_FILE_SHA256_PRE STREQUAL CMKR_LIST_FILE_SHA256_POST) 216 | # Copy the now-generated CMakeLists.txt to CMakerLists.txt 217 | # This is done because you cannot include() a file you are currently in 218 | configure_file(CMakeLists.txt "${CMKR_TEMP_FILE}" COPYONLY) 219 | 220 | # Add the macro required for the hack at the start of the cmkr macro 221 | set_source_files_properties("${CMKR_TEMP_FILE}" PROPERTIES 222 | CMKR_CURRENT_LIST_FILE "${CMAKE_CURRENT_LIST_FILE}" 223 | ) 224 | 225 | # 'Execute' the newly-generated CMakeLists.txt 226 | include("${CMKR_TEMP_FILE}") 227 | 228 | # Delete the generated file 229 | file(REMOVE "${CMKR_TEMP_FILE}") 230 | 231 | # Do not execute the rest of the original CMakeLists.txt 232 | return() 233 | endif() 234 | # Resume executing the unmodified CMakeLists.txt 235 | endif() 236 | endmacro() 237 | -------------------------------------------------------------------------------- /src/EfiCMake/Efi.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // Modified version for C++ compatibility 4 | #include "ProcessorBind.hpp" 5 | 6 | extern "C" 7 | { 8 | #include 9 | } -------------------------------------------------------------------------------- /src/EfiCMake/ProcessorBind.hpp: -------------------------------------------------------------------------------- 1 | /** @file 2 | Processor or Compiler specific defines and types x64 (Intel 64, AMD64). 3 | 4 | Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.
5 | SPDX-License-Identifier: BSD-2-Clause-Patent 6 | 7 | **/ 8 | 9 | #ifndef __PROCESSOR_BIND_H__ 10 | #define __PROCESSOR_BIND_H__ 11 | 12 | /// 13 | /// Define the processor type so other code can make processor based choices 14 | /// 15 | #define MDE_CPU_X64 16 | 17 | // 18 | // Make sure we are using the correct packing rules per EFI specification 19 | // 20 | #if !defined (__GNUC__) 21 | #pragma pack() 22 | #endif 23 | 24 | #if defined (__GNUC__) && defined (__pic__) && !defined (USING_LTO) && !defined (__APPLE__) 25 | // 26 | // Mark all symbol declarations and references as hidden, meaning they will 27 | // not be subject to symbol preemption. This allows the compiler to refer to 28 | // symbols directly using relative references rather than via the GOT, which 29 | // contains absolute symbol addresses that are subject to runtime relocation. 30 | // 31 | // The LTO linker will not emit GOT based relocations when all symbol 32 | // references can be resolved locally, and so there is no need to set the 33 | // pragma in that case (and doing so will cause other issues). 34 | // 35 | #pragma GCC visibility push (hidden) 36 | #endif 37 | 38 | #if defined (__INTEL_COMPILER) 39 | // 40 | // Disable ICC's remark #869: "Parameter" was never referenced warning. 41 | // This is legal ANSI C code so we disable the remark that is turned on with -Wall 42 | // 43 | #pragma warning ( disable : 869 ) 44 | 45 | // 46 | // Disable ICC's remark #1418: external function definition with no prior declaration. 47 | // This is legal ANSI C code so we disable the remark that is turned on with /W4 48 | // 49 | #pragma warning ( disable : 1418 ) 50 | 51 | // 52 | // Disable ICC's remark #1419: external declaration in primary source file 53 | // This is legal ANSI C code so we disable the remark that is turned on with /W4 54 | // 55 | #pragma warning ( disable : 1419 ) 56 | 57 | // 58 | // Disable ICC's remark #593: "Variable" was set but never used. 59 | // This is legal ANSI C code so we disable the remark that is turned on with /W4 60 | // 61 | #pragma warning ( disable : 593 ) 62 | 63 | #endif 64 | 65 | #if defined (_MSC_EXTENSIONS) 66 | 67 | // 68 | // Disable warning that make it impossible to compile at /W4 69 | // This only works for Microsoft* tools 70 | // 71 | 72 | // 73 | // Disabling bitfield type checking warnings. 74 | // 75 | #pragma warning ( disable : 4214 ) 76 | 77 | // 78 | // Disabling the unreferenced formal parameter warnings. 79 | // 80 | #pragma warning ( disable : 4100 ) 81 | 82 | // 83 | // Disable slightly different base types warning as CHAR8 * can not be set 84 | // to a constant string. 85 | // 86 | #pragma warning ( disable : 4057 ) 87 | 88 | // 89 | // ASSERT(FALSE) or while (TRUE) are legal constructs so suppress this warning 90 | // 91 | #pragma warning ( disable : 4127 ) 92 | 93 | // 94 | // This warning is caused by functions defined but not used. For precompiled header only. 95 | // 96 | #pragma warning ( disable : 4505 ) 97 | 98 | // 99 | // This warning is caused by empty (after preprocessing) source file. For precompiled header only. 100 | // 101 | #pragma warning ( disable : 4206 ) 102 | 103 | #if defined (_MSC_VER) && _MSC_VER >= 1800 104 | 105 | // 106 | // Disable these warnings for VS2013. 107 | // 108 | 109 | // 110 | // This warning is for potentially uninitialized local variable, and it may cause false 111 | // positive issues in VS2013 and VS2015 build 112 | // 113 | #pragma warning ( disable : 4701 ) 114 | 115 | // 116 | // This warning is for potentially uninitialized local pointer variable, and it may cause 117 | // false positive issues in VS2013 and VS2015 build 118 | // 119 | #pragma warning ( disable : 4703 ) 120 | 121 | #endif 122 | 123 | #endif 124 | 125 | #if defined (_MSC_EXTENSIONS) 126 | // 127 | // use Microsoft C compiler dependent integer width types 128 | // 129 | 130 | /// 131 | /// 8-byte unsigned value 132 | /// 133 | typedef unsigned __int64 UINT64; 134 | /// 135 | /// 8-byte signed value 136 | /// 137 | typedef __int64 INT64; 138 | /// 139 | /// 4-byte unsigned value 140 | /// 141 | typedef unsigned __int32 UINT32; 142 | /// 143 | /// 4-byte signed value 144 | /// 145 | typedef __int32 INT32; 146 | /// 147 | /// 2-byte unsigned value 148 | /// 149 | typedef unsigned short UINT16; 150 | /// 151 | /// 2-byte Character. Unless otherwise specified all strings are stored in the 152 | /// UTF-16 encoding format as defined by Unicode 2.1 and ISO/IEC 10646 standards. 153 | /// 154 | typedef wchar_t CHAR16; 155 | /// 156 | /// 2-byte signed value 157 | /// 158 | typedef short INT16; 159 | /// 160 | /// Logical Boolean. 1-byte value containing 0 for FALSE or a 1 for TRUE. Other 161 | /// values are undefined. 162 | /// 163 | typedef unsigned char BOOLEAN; 164 | /// 165 | /// 1-byte unsigned value 166 | /// 167 | typedef unsigned char UINT8; 168 | /// 169 | /// 1-byte Character 170 | /// 171 | typedef char CHAR8; 172 | /// 173 | /// 1-byte signed value 174 | /// 175 | typedef signed char INT8; 176 | #else 177 | /// 178 | /// 8-byte unsigned value 179 | /// 180 | typedef unsigned long long UINT64; 181 | /// 182 | /// 8-byte signed value 183 | /// 184 | typedef long long INT64; 185 | /// 186 | /// 4-byte unsigned value 187 | /// 188 | typedef unsigned int UINT32; 189 | /// 190 | /// 4-byte signed value 191 | /// 192 | typedef int INT32; 193 | /// 194 | /// 2-byte unsigned value 195 | /// 196 | typedef unsigned short UINT16; 197 | /// 198 | /// 2-byte Character. Unless otherwise specified all strings are stored in the 199 | /// UTF-16 encoding format as defined by Unicode 2.1 and ISO/IEC 10646 standards. 200 | /// 201 | typedef wchar_t CHAR16; 202 | /// 203 | /// 2-byte signed value 204 | /// 205 | typedef short INT16; 206 | /// 207 | /// Logical Boolean. 1-byte value containing 0 for FALSE or a 1 for TRUE. Other 208 | /// values are undefined. 209 | /// 210 | typedef unsigned char BOOLEAN; 211 | /// 212 | /// 1-byte unsigned value 213 | /// 214 | typedef unsigned char UINT8; 215 | /// 216 | /// 1-byte Character 217 | /// 218 | typedef char CHAR8; 219 | /// 220 | /// 1-byte signed value 221 | /// 222 | typedef signed char INT8; 223 | #endif 224 | 225 | /// 226 | /// Unsigned value of native width. (4 bytes on supported 32-bit processor instructions, 227 | /// 8 bytes on supported 64-bit processor instructions) 228 | /// 229 | typedef UINT64 UINTN; 230 | /// 231 | /// Signed value of native width. (4 bytes on supported 32-bit processor instructions, 232 | /// 8 bytes on supported 64-bit processor instructions) 233 | /// 234 | typedef INT64 INTN; 235 | 236 | // 237 | // Processor specific defines 238 | // 239 | 240 | /// 241 | /// A value of native width with the highest bit set. 242 | /// 243 | #define MAX_BIT 0x8000000000000000ULL 244 | /// 245 | /// A value of native width with the two highest bits set. 246 | /// 247 | #define MAX_2_BITS 0xC000000000000000ULL 248 | 249 | /// 250 | /// Maximum legal x64 address 251 | /// 252 | #define MAX_ADDRESS 0xFFFFFFFFFFFFFFFFULL 253 | 254 | /// 255 | /// Maximum usable address at boot time 256 | /// 257 | #define MAX_ALLOC_ADDRESS MAX_ADDRESS 258 | 259 | /// 260 | /// Maximum legal x64 INTN and UINTN values. 261 | /// 262 | #define MAX_INTN ((INTN)0x7FFFFFFFFFFFFFFFULL) 263 | #define MAX_UINTN ((UINTN)0xFFFFFFFFFFFFFFFFULL) 264 | 265 | /// 266 | /// Minimum legal x64 INTN value. 267 | /// 268 | #define MIN_INTN (((INTN)-9223372036854775807LL) - 1) 269 | 270 | /// 271 | /// The stack alignment required for x64 272 | /// 273 | #define CPU_STACK_ALIGNMENT 16 274 | 275 | /// 276 | /// Page allocation granularity for x64 277 | /// 278 | #define DEFAULT_PAGE_ALLOCATION_GRANULARITY (0x1000) 279 | #define RUNTIME_PAGE_ALLOCATION_GRANULARITY (0x1000) 280 | 281 | // 282 | // Modifier to ensure that all protocol member functions and EFI intrinsics 283 | // use the correct C calling convention. All protocol member functions and 284 | // EFI intrinsics are required to modify their member functions with EFIAPI. 285 | // 286 | #ifdef EFIAPI 287 | /// 288 | /// If EFIAPI is already defined, then we use that definition. 289 | /// 290 | #elif defined (_MSC_EXTENSIONS) 291 | /// 292 | /// Microsoft* compiler specific method for EFIAPI calling convention. 293 | /// 294 | #define EFIAPI __cdecl 295 | #elif defined (__GNUC__) 296 | /// 297 | /// Define the standard calling convention regardless of optimization level. 298 | /// The GCC support assumes a GCC compiler that supports the EFI ABI. The EFI 299 | /// ABI is much closer to the x64 Microsoft* ABI than standard x64 (x86-64) 300 | /// GCC ABI. Thus a standard x64 (x86-64) GCC compiler can not be used for 301 | /// x64. Warning the assembly code in the MDE x64 does not follow the correct 302 | /// ABI for the standard x64 (x86-64) GCC. 303 | /// 304 | #define EFIAPI 305 | #else 306 | /// 307 | /// The default for a non Microsoft* or GCC compiler is to assume the EFI ABI 308 | /// is the standard. 309 | /// 310 | #define EFIAPI 311 | #endif 312 | 313 | #if defined (__GNUC__) || defined (__clang__) 314 | /// 315 | /// For GNU assembly code, .global or .globl can declare global symbols. 316 | /// Define this macro to unify the usage. 317 | /// 318 | #define ASM_GLOBAL .globl 319 | #endif 320 | 321 | /** 322 | Return the pointer to the first instruction of a function given a function pointer. 323 | On x64 CPU architectures, these two pointer values are the same, 324 | so the implementation of this macro is very simple. 325 | 326 | @param FunctionPointer A pointer to a function. 327 | 328 | @return The pointer to the first instruction of a function given a function pointer. 329 | 330 | **/ 331 | #define FUNCTION_ENTRY_POINT(FunctionPointer) (VOID *)(UINTN)(FunctionPointer) 332 | 333 | #ifndef __USER_LABEL_PREFIX__ 334 | #define __USER_LABEL_PREFIX__ 335 | #endif 336 | 337 | #endif 338 | -------------------------------------------------------------------------------- /src/EfiCMake/main.cpp: -------------------------------------------------------------------------------- 1 | #include "Efi.hpp" 2 | 3 | EFI_STATUS EFIAPI EfiEntry(EFI_HANDLE imageHandle, EFI_SYSTEM_TABLE* systemTable) 4 | { 5 | systemTable->ConOut->OutputString(systemTable->ConOut, L"Hello from CMake!\n"); 6 | return EFI_SUCCESS; 7 | } 8 | --------------------------------------------------------------------------------