-
Notifications
You must be signed in to change notification settings - Fork 13k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[libc] init uefi os target #120687
[libc] init uefi os target #120687
Conversation
@llvm/pr-subscribers-libc Author: Tristan Ross (RossComputerGuy) ChangesNot even a hello world can run yet but this adds in all the necessary files and makes the necessary changes to start with UEFI. With #120632 being used along side this PR, I can generate a simple empty main program. This uses the triples Testing can be done by running something like this:
Based on the UEFI 2.10 spec. Patch is 73.73 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/120687.diff 46 Files Affected:
diff --git a/libc/cmake/modules/LLVMLibCArchitectures.cmake b/libc/cmake/modules/LLVMLibCArchitectures.cmake
index fbb1091ddabab4..9638b0b117f0fb 100644
--- a/libc/cmake/modules/LLVMLibCArchitectures.cmake
+++ b/libc/cmake/modules/LLVMLibCArchitectures.cmake
@@ -69,6 +69,10 @@ function(get_arch_and_system_from_triple triple arch_var sys_var)
set(target_sys "darwin")
endif()
+ if(target_sys STREQUAL "unknown")
+ list(GET triple_comps -1 target_sys)
+ endif()
+
# Setting OS name for GPU architectures.
list(GET triple_comps -1 gpu_target_sys)
if(gpu_target_sys MATCHES "^amdhsa" OR gpu_target_sys MATCHES "^cuda")
@@ -187,6 +191,8 @@ elseif(LIBC_TARGET_OS STREQUAL "windows")
set(LIBC_TARGET_OS_IS_WINDOWS TRUE)
elseif(LIBC_TARGET_OS STREQUAL "gpu")
set(LIBC_TARGET_OS_IS_GPU TRUE)
+elseif(LIBC_TARGET_OS STREQUAL "uefi")
+ set(LIBC_TARGET_OS_IS_UEFI TRUE)
else()
message(FATAL_ERROR
"Unsupported libc target operating system ${LIBC_TARGET_OS}")
diff --git a/libc/config/uefi/config.json b/libc/config/uefi/config.json
new file mode 100644
index 00000000000000..b60dde9ef040ac
--- /dev/null
+++ b/libc/config/uefi/config.json
@@ -0,0 +1,29 @@
+{
+ "errno": {
+ "LIBC_CONF_ERRNO_MODE": {
+ "value": "LIBC_ERRNO_MODE_DEFAULT"
+ }
+ },
+ "printf": {
+ "LIBC_CONF_PRINTF_DISABLE_FLOAT": {
+ "value": true
+ },
+ "LIBC_CONF_PRINTF_DISABLE_INDEX_MODE": {
+ "value": true
+ },
+ "LIBC_CONF_PRINTF_DISABLE_WRITE_INT": {
+ "value": true
+ },
+ "LIBC_CONF_PRINTF_FLOAT_TO_STR_USE_MEGA_LONG_DOUBLE_TABLE": {
+ "value": false
+ },
+ "LIBC_CONF_PRINTF_DISABLE_STRERROR": {
+ "value": true
+ }
+ },
+ "qsort": {
+ "LIBC_CONF_QSORT_IMPL": {
+ "value": "LIBC_QSORT_HEAP_SORT"
+ }
+ }
+}
diff --git a/libc/config/uefi/entrypoints.txt b/libc/config/uefi/entrypoints.txt
new file mode 100644
index 00000000000000..664a4d2ca46405
--- /dev/null
+++ b/libc/config/uefi/entrypoints.txt
@@ -0,0 +1,450 @@
+set(TARGET_LIBC_ENTRYPOINTS
+ # ctype.h entrypoints
+ libc.src.ctype.isalnum
+ libc.src.ctype.isalpha
+ libc.src.ctype.isascii
+ libc.src.ctype.isblank
+ libc.src.ctype.iscntrl
+ libc.src.ctype.isdigit
+ libc.src.ctype.isgraph
+ libc.src.ctype.islower
+ libc.src.ctype.isprint
+ libc.src.ctype.ispunct
+ libc.src.ctype.isspace
+ libc.src.ctype.isupper
+ libc.src.ctype.isxdigit
+ libc.src.ctype.toascii
+ libc.src.ctype.tolower
+ libc.src.ctype.toupper
+
+ # errno.h entrypoints
+ libc.src.errno.errno
+
+ # setjmp.h entrypoints
+ libc.src.setjmp.longjmp
+ libc.src.setjmp.setjmp
+
+ # string.h entrypoints
+ libc.src.string.memccpy
+ libc.src.string.memchr
+ libc.src.string.memcmp
+ libc.src.string.memcpy
+ libc.src.string.memmem
+ libc.src.string.memmove
+ libc.src.string.mempcpy
+ libc.src.string.memrchr
+ libc.src.string.memset
+ libc.src.string.memset_explicit
+ libc.src.string.stpcpy
+ libc.src.string.stpncpy
+ libc.src.string.strcasestr
+ libc.src.string.strcat
+ libc.src.string.strchr
+ libc.src.string.strchrnul
+ libc.src.string.strcmp
+ libc.src.string.strcoll
+ libc.src.string.strcpy
+ libc.src.string.strcspn
+ libc.src.string.strerror
+ libc.src.string.strerror_r
+ libc.src.string.strlcat
+ libc.src.string.strlcpy
+ libc.src.string.strlen
+ libc.src.string.strncat
+ libc.src.string.strncmp
+ libc.src.string.strncpy
+ libc.src.string.strnlen
+ libc.src.string.strpbrk
+ libc.src.string.strrchr
+ libc.src.string.strsep
+ libc.src.string.strspn
+ libc.src.string.strstr
+ libc.src.string.strtok
+ libc.src.string.strtok_r
+ libc.src.string.strxfrm
+
+ # strings.h entrypoints
+ libc.src.strings.bcmp
+ libc.src.strings.bcopy
+ libc.src.strings.bzero
+ libc.src.strings.index
+ libc.src.strings.rindex
+ libc.src.strings.strcasecmp
+ libc.src.strings.strncasecmp
+
+ # inttypes.h entrypoints
+ libc.src.inttypes.imaxabs
+ libc.src.inttypes.imaxdiv
+ libc.src.inttypes.strtoimax
+ libc.src.inttypes.strtoumax
+
+ # stdbit.h entrypoints
+ libc.src.stdbit.stdc_bit_ceil_uc
+ libc.src.stdbit.stdc_bit_ceil_ui
+ libc.src.stdbit.stdc_bit_ceil_ul
+ libc.src.stdbit.stdc_bit_ceil_ull
+ libc.src.stdbit.stdc_bit_ceil_us
+ libc.src.stdbit.stdc_bit_floor_uc
+ libc.src.stdbit.stdc_bit_floor_ui
+ libc.src.stdbit.stdc_bit_floor_ul
+ libc.src.stdbit.stdc_bit_floor_ull
+ libc.src.stdbit.stdc_bit_floor_us
+ libc.src.stdbit.stdc_bit_width_uc
+ libc.src.stdbit.stdc_bit_width_ui
+ libc.src.stdbit.stdc_bit_width_ul
+ libc.src.stdbit.stdc_bit_width_ull
+ libc.src.stdbit.stdc_bit_width_us
+ libc.src.stdbit.stdc_count_ones_uc
+ libc.src.stdbit.stdc_count_ones_ui
+ libc.src.stdbit.stdc_count_ones_ul
+ libc.src.stdbit.stdc_count_ones_ull
+ libc.src.stdbit.stdc_count_ones_us
+ libc.src.stdbit.stdc_count_zeros_uc
+ libc.src.stdbit.stdc_count_zeros_ui
+ libc.src.stdbit.stdc_count_zeros_ul
+ libc.src.stdbit.stdc_count_zeros_ull
+ libc.src.stdbit.stdc_count_zeros_us
+ libc.src.stdbit.stdc_first_leading_one_uc
+ libc.src.stdbit.stdc_first_leading_one_ui
+ libc.src.stdbit.stdc_first_leading_one_ul
+ libc.src.stdbit.stdc_first_leading_one_ull
+ libc.src.stdbit.stdc_first_leading_one_us
+ libc.src.stdbit.stdc_first_leading_zero_uc
+ libc.src.stdbit.stdc_first_leading_zero_ui
+ libc.src.stdbit.stdc_first_leading_zero_ul
+ libc.src.stdbit.stdc_first_leading_zero_ull
+ libc.src.stdbit.stdc_first_leading_zero_us
+ libc.src.stdbit.stdc_first_trailing_one_uc
+ libc.src.stdbit.stdc_first_trailing_one_ui
+ libc.src.stdbit.stdc_first_trailing_one_ul
+ libc.src.stdbit.stdc_first_trailing_one_ull
+ libc.src.stdbit.stdc_first_trailing_one_us
+ libc.src.stdbit.stdc_first_trailing_zero_uc
+ libc.src.stdbit.stdc_first_trailing_zero_ui
+ libc.src.stdbit.stdc_first_trailing_zero_ul
+ libc.src.stdbit.stdc_first_trailing_zero_ull
+ libc.src.stdbit.stdc_first_trailing_zero_us
+ libc.src.stdbit.stdc_has_single_bit_uc
+ libc.src.stdbit.stdc_has_single_bit_ui
+ libc.src.stdbit.stdc_has_single_bit_ul
+ libc.src.stdbit.stdc_has_single_bit_ull
+ libc.src.stdbit.stdc_has_single_bit_us
+ libc.src.stdbit.stdc_leading_ones_uc
+ libc.src.stdbit.stdc_leading_ones_ui
+ libc.src.stdbit.stdc_leading_ones_ul
+ libc.src.stdbit.stdc_leading_ones_ull
+ libc.src.stdbit.stdc_leading_ones_us
+ libc.src.stdbit.stdc_leading_zeros_uc
+ libc.src.stdbit.stdc_leading_zeros_ui
+ libc.src.stdbit.stdc_leading_zeros_ul
+ libc.src.stdbit.stdc_leading_zeros_ull
+ libc.src.stdbit.stdc_leading_zeros_us
+ libc.src.stdbit.stdc_trailing_ones_uc
+ libc.src.stdbit.stdc_trailing_ones_ui
+ libc.src.stdbit.stdc_trailing_ones_ul
+ libc.src.stdbit.stdc_trailing_ones_ull
+ libc.src.stdbit.stdc_trailing_ones_us
+ libc.src.stdbit.stdc_trailing_zeros_uc
+ libc.src.stdbit.stdc_trailing_zeros_ui
+ libc.src.stdbit.stdc_trailing_zeros_ul
+ libc.src.stdbit.stdc_trailing_zeros_ull
+ libc.src.stdbit.stdc_trailing_zeros_us
+
+ # stdlib.h entrypoints
+ libc.src.stdlib._Exit
+ libc.src.stdlib.abs
+ libc.src.stdlib.aligned_alloc
+ libc.src.stdlib.atof
+ libc.src.stdlib.atoi
+ libc.src.stdlib.atol
+ libc.src.stdlib.atoll
+ libc.src.stdlib.bsearch
+ libc.src.stdlib.calloc
+ libc.src.stdlib.div
+ libc.src.stdlib.free
+ libc.src.stdlib.labs
+ libc.src.stdlib.ldiv
+ libc.src.stdlib.llabs
+ libc.src.stdlib.lldiv
+ libc.src.stdlib.malloc
+ libc.src.stdlib.qsort
+ libc.src.stdlib.rand
+ libc.src.stdlib.realloc
+ libc.src.stdlib.srand
+ libc.src.stdlib.strtod
+ libc.src.stdlib.strtof
+ libc.src.stdlib.strtol
+ libc.src.stdlib.strtold
+ libc.src.stdlib.strtoll
+ libc.src.stdlib.strtoul
+ libc.src.stdlib.strtoull
+
+ # time.h entrypoints
+ libc.src.time.asctime
+ libc.src.time.asctime_r
+ libc.src.time.ctime
+ libc.src.time.ctime_r
+ libc.src.time.difftime
+ libc.src.time.gmtime
+ libc.src.time.gmtime_r
+ libc.src.time.mktime
+)
+
+set(TARGET_LIBM_ENTRYPOINTS
+ # fenv.h entrypoints
+ libc.src.fenv.feclearexcept
+ libc.src.fenv.fedisableexcept
+ libc.src.fenv.feenableexcept
+ libc.src.fenv.fegetenv
+ libc.src.fenv.fegetexcept
+ libc.src.fenv.fegetexceptflag
+ libc.src.fenv.fegetround
+ libc.src.fenv.feholdexcept
+ libc.src.fenv.feraiseexcept
+ libc.src.fenv.fesetenv
+ libc.src.fenv.fesetexcept
+ libc.src.fenv.fesetexceptflag
+ libc.src.fenv.fesetround
+ libc.src.fenv.fetestexcept
+ libc.src.fenv.fetestexceptflag
+ libc.src.fenv.feupdateenv
+
+ # math.h entrypoints
+ libc.src.math.acosf
+ libc.src.math.acoshf
+ libc.src.math.asinf
+ libc.src.math.asinhf
+ libc.src.math.atan2
+ libc.src.math.atan2f
+ libc.src.math.atanf
+ libc.src.math.atanhf
+ libc.src.math.canonicalize
+ libc.src.math.canonicalizef
+ libc.src.math.canonicalizel
+ libc.src.math.cbrt
+ libc.src.math.cbrtf
+ libc.src.math.ceil
+ libc.src.math.ceilf
+ libc.src.math.ceill
+ libc.src.math.copysign
+ libc.src.math.copysignf
+ libc.src.math.copysignl
+ libc.src.math.cos
+ libc.src.math.cosf
+ libc.src.math.coshf
+ libc.src.math.erff
+ libc.src.math.exp
+ libc.src.math.exp10
+ libc.src.math.exp10f
+ libc.src.math.exp2
+ libc.src.math.exp2f
+ libc.src.math.exp2m1f
+ libc.src.math.expf
+ libc.src.math.expm1
+ libc.src.math.expm1f
+ libc.src.math.fabs
+ libc.src.math.fabsf
+ libc.src.math.fabsl
+ libc.src.math.fdim
+ libc.src.math.fdimf
+ libc.src.math.fdiml
+ libc.src.math.floor
+ libc.src.math.floorf
+ libc.src.math.floorl
+ libc.src.math.fma
+ libc.src.math.fmaf
+ libc.src.math.fmax
+ libc.src.math.fmaxf
+ libc.src.math.fmaximum
+ libc.src.math.fmaximum_mag
+ libc.src.math.fmaximum_mag_num
+ libc.src.math.fmaximum_mag_numf
+ libc.src.math.fmaximum_mag_numl
+ libc.src.math.fmaximum_magf
+ libc.src.math.fmaximum_magl
+ libc.src.math.fmaximum_num
+ libc.src.math.fmaximum_numf
+ libc.src.math.fmaximum_numl
+ libc.src.math.fmaximumf
+ libc.src.math.fmaximuml
+ libc.src.math.fmaxl
+ libc.src.math.fmin
+ libc.src.math.fminf
+ libc.src.math.fminimum
+ libc.src.math.fminimum_mag
+ libc.src.math.fminimum_mag_num
+ libc.src.math.fminimum_mag_numf
+ libc.src.math.fminimum_mag_numl
+ libc.src.math.fminimum_magf
+ libc.src.math.fminimum_magl
+ libc.src.math.fminimum_num
+ libc.src.math.fminimum_numf
+ libc.src.math.fminimum_numl
+ libc.src.math.fminimumf
+ libc.src.math.fminimuml
+ libc.src.math.fminl
+ libc.src.math.fmod
+ libc.src.math.fmodf
+ libc.src.math.fmodl
+ libc.src.math.fmul
+ libc.src.math.frexp
+ libc.src.math.frexpf
+ libc.src.math.frexpl
+ libc.src.math.fromfp
+ libc.src.math.fromfpf
+ libc.src.math.fromfpl
+ libc.src.math.fromfpx
+ libc.src.math.fromfpxf
+ libc.src.math.fromfpxl
+ libc.src.math.hypot
+ libc.src.math.hypotf
+ libc.src.math.ilogb
+ libc.src.math.ilogbf
+ libc.src.math.ilogbl
+ libc.src.math.isnan
+ libc.src.math.isnanf
+ libc.src.math.isnanl
+ libc.src.math.ldexp
+ libc.src.math.ldexpf
+ libc.src.math.ldexpl
+ libc.src.math.llogb
+ libc.src.math.llogbf
+ libc.src.math.llogbl
+ libc.src.math.llrint
+ libc.src.math.llrintf
+ libc.src.math.llrintl
+ libc.src.math.llround
+ libc.src.math.llroundf
+ libc.src.math.llroundl
+ libc.src.math.log
+ libc.src.math.log10
+ libc.src.math.log10f
+ libc.src.math.log1p
+ libc.src.math.log1pf
+ libc.src.math.log2
+ libc.src.math.log2f
+ libc.src.math.logb
+ libc.src.math.logbf
+ libc.src.math.logbl
+ libc.src.math.logf
+ libc.src.math.lrint
+ libc.src.math.lrintf
+ libc.src.math.lrintl
+ libc.src.math.lround
+ libc.src.math.lroundf
+ libc.src.math.lroundl
+ libc.src.math.modf
+ libc.src.math.modff
+ libc.src.math.modfl
+ libc.src.math.nan
+ libc.src.math.nanf
+ libc.src.math.nanl
+ libc.src.math.nearbyint
+ libc.src.math.nearbyintf
+ libc.src.math.nearbyintl
+ libc.src.math.nextafter
+ libc.src.math.nextafterf
+ libc.src.math.nextafterl
+ libc.src.math.nextdown
+ libc.src.math.nextdownf
+ libc.src.math.nextdownl
+ libc.src.math.nexttoward
+ libc.src.math.nexttowardf
+ libc.src.math.nexttowardl
+ libc.src.math.nextup
+ libc.src.math.nextupf
+ libc.src.math.nextupl
+ libc.src.math.pow
+ libc.src.math.powf
+ libc.src.math.remainder
+ libc.src.math.remainderf
+ libc.src.math.remainderl
+ libc.src.math.remquo
+ libc.src.math.remquof
+ libc.src.math.remquol
+ libc.src.math.rint
+ libc.src.math.rintf
+ libc.src.math.rintl
+ libc.src.math.round
+ libc.src.math.roundeven
+ libc.src.math.roundevenf
+ libc.src.math.roundevenl
+ libc.src.math.roundf
+ libc.src.math.roundl
+ libc.src.math.scalbln
+ libc.src.math.scalblnf
+ libc.src.math.scalblnl
+ libc.src.math.scalbn
+ libc.src.math.scalbnf
+ libc.src.math.scalbnl
+ libc.src.math.sin
+ libc.src.math.sincos
+ libc.src.math.sincosf
+ libc.src.math.sinf
+ libc.src.math.sinhf
+ libc.src.math.sqrt
+ libc.src.math.sqrtf
+ libc.src.math.sqrtl
+ libc.src.math.tan
+ libc.src.math.tanf
+ libc.src.math.tanhf
+ libc.src.math.trunc
+ libc.src.math.truncf
+ libc.src.math.truncl
+ libc.src.math.ufromfp
+ libc.src.math.ufromfpf
+ libc.src.math.ufromfpl
+ libc.src.math.ufromfpx
+ libc.src.math.ufromfpxf
+ libc.src.math.ufromfpxl
+)
+
+if(LIBC_COMPILER_HAS_FIXED_POINT)
+ list(APPEND TARGET_LIBM_ENTRYPOINTS
+ # stdfix.h _Fract and _Accum entrypoints
+ libc.src.stdfix.abshk
+ libc.src.stdfix.abshr
+ libc.src.stdfix.absk
+ libc.src.stdfix.abslk
+ libc.src.stdfix.abslr
+ libc.src.stdfix.absr
+ libc.src.stdfix.exphk
+ libc.src.stdfix.expk
+ libc.src.stdfix.roundhk
+ libc.src.stdfix.roundhr
+ libc.src.stdfix.roundk
+ libc.src.stdfix.roundlk
+ libc.src.stdfix.roundlr
+ libc.src.stdfix.roundr
+ libc.src.stdfix.rounduhk
+ libc.src.stdfix.rounduhr
+ libc.src.stdfix.rounduk
+ libc.src.stdfix.roundulk
+ libc.src.stdfix.roundulr
+ libc.src.stdfix.roundur
+ libc.src.stdfix.sqrtuhk
+ libc.src.stdfix.sqrtuhr
+ libc.src.stdfix.sqrtuk
+ libc.src.stdfix.sqrtur
+ libc.src.stdfix.sqrtulr
+ libc.src.stdfix.uhksqrtus
+ libc.src.stdfix.uksqrtui
+ libc.src.stdfix.hrbits
+ libc.src.stdfix.uhrbits
+ libc.src.stdfix.rbits
+ libc.src.stdfix.urbits
+ libc.src.stdfix.lrbits
+ libc.src.stdfix.ulrbits
+ libc.src.stdfix.hkbits
+ libc.src.stdfix.uhkbits
+ libc.src.stdfix.kbits
+ libc.src.stdfix.ukbits
+ libc.src.stdfix.lkbits
+ libc.src.stdfix.ulkbits
+ )
+endif()
+
+set(TARGET_LLVMLIBC_ENTRYPOINTS
+ ${TARGET_LIBC_ENTRYPOINTS}
+ ${TARGET_LIBM_ENTRYPOINTS}
+)
diff --git a/libc/config/uefi/headers.txt b/libc/config/uefi/headers.txt
new file mode 100644
index 00000000000000..bf8dee1e6f2a69
--- /dev/null
+++ b/libc/config/uefi/headers.txt
@@ -0,0 +1,20 @@
+set(TARGET_PUBLIC_HEADERS
+ libc.include.assert
+ libc.include.ctype
+ libc.include.errno
+ libc.include.features
+ libc.include.fenv
+ libc.include.float
+ libc.include.inttypes
+ libc.include.math
+ libc.include.setjmp
+ libc.include.stdfix
+ libc.include.stdint
+ libc.include.stdlib
+ libc.include.string
+ libc.include.strings
+ libc.include.sys_queue
+ libc.include.time
+ libc.include.uefi
+ libc.include.uchar
+)
diff --git a/libc/hdrgen/yaml/Uefi.yaml b/libc/hdrgen/yaml/Uefi.yaml
new file mode 100644
index 00000000000000..f17e629c87cc7e
--- /dev/null
+++ b/libc/hdrgen/yaml/Uefi.yaml
@@ -0,0 +1,11 @@
+header: Uefi.h
+standards: UEFI
+macros: []
+types:
+ - type_name: EFI_BOOT_SERVICES
+ - type_name: EFI_GUID
+ - type_name: EFI_STATUS
+ - type_name: EFI_SYSTEM_TABLE
+enums: []
+functions: []
+objects: []
diff --git a/libc/include/CMakeLists.txt b/libc/include/CMakeLists.txt
index 18ce8e22d1a0ac..7acde83e5ea6e9 100644
--- a/libc/include/CMakeLists.txt
+++ b/libc/include/CMakeLists.txt
@@ -763,6 +763,23 @@ if(LIBC_TARGET_OS_IS_GPU)
)
endif()
+if(LIBC_TARGET_OS_IS_UEFI)
+ add_subdirectory(uefi)
+
+ # UEFI spec references "Uefi.h" so we use that name for compatibility
+ add_header_macro(
+ uefi
+ ../libc/hdrgen/yaml/Uefi.yaml
+ Uefi.h.def
+ Uefi.h
+ DEPENDS
+ .llvm_libc_common_h
+ .llvm-libc-types.EFI_GUID
+ .llvm-libc-types.EFI_STATUS
+ .llvm-libc-types.EFI_SYSTEM_TABLE
+ )
+endif()
+
if(NOT LLVM_LIBC_FULL_BUILD)
# We don't install headers in non-fullbuild mode.
return()
diff --git a/libc/include/Uefi.h.def b/libc/include/Uefi.h.def
new file mode 100644
index 00000000000000..6655e13579cd8d
--- /dev/null
+++ b/libc/include/Uefi.h.def
@@ -0,0 +1,16 @@
+//===-- UEFI header uefi.h --------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_UEFI_H
+#define LLVM_LIBC_UEFI_H
+
+#include "__llvm-libc-common.h"
+
+%%public_api()
+
+#endif // LLVM_LIBC_UEFI_H
diff --git a/libc/include/llvm-libc-macros/CMakeLists.txt b/libc/include/llvm-libc-macros/CMakeLists.txt
index 9d5d9f65442889..bdad3edbfb6d1c 100644
--- a/libc/include/llvm-libc-macros/CMakeLists.txt
+++ b/libc/include/llvm-libc-macros/CMakeLists.txt
@@ -321,3 +321,9 @@ add_macro_header(
HDR
pthread-macros.h
)
+
+add_macro_header(
+ EFIAPI_macros
+ HDR
+ EFIAPI-macros.h
+)
diff --git a/libc/include/llvm-libc-macros/EFIAPI-macros.h b/libc/include/llvm-libc-macros/EFIAPI-macros.h
new file mode 100644
index 00000000000000..d6cc1784bb7863
--- /dev/null
+++ b/libc/include/llvm-libc-macros/EFIAPI-macros.h
@@ -0,0 +1,10 @@
+#ifndef LLVM_LIBC_MACROS_EFIAPI_MACROS_H
+#define LLVM_LIBC_MACROS_EFIAPI_MACROS_H
+
+#if defined(__x86_64__) && !defined(__ILP32__)
+#define EFIAPI __attribute__((ms_abi))
+#else
+#define EFIAPI
+#endif
+
+#endif // LLVM_LIBC_MACROS_EFIAPI_MACROS_H
diff --git a/libc/include/llvm-libc-types/CMakeLists.txt b/libc/include/llvm-libc-types/CMakeLists.txt
index ee734eafce3620..699df893378d05 100644
--- a/libc/include/llvm-libc-types/CMakeLists.txt
+++ b/libc/include/llvm-libc-types/CMakeLists.txt
@@ -155,3 +155,124 @@ DEPENDS
add_header(locale_t HDR locale_t.h)
add_header(struct_lconv HDR struct_lconv.h)
add_header(stdfix-types HDR stdfix-types.h)
+
+# UEFI
+add_header(EFI_GUID HDR EFI_GUID.h DEPENDS libc.include.llvm-libc-macros.stdint_macros)
+add_header(EFI_CONFIGURATION_TABLE HDR EFI_CONFIGURATION_TABLE.h DEPENDS .EFI_GUID)
+
+add_header(EFI_PHYSICAL_ADDRESS HDR EFI_PHYSICAL_ADDRESS.h DEPENDS libc.include.llvm-libc-macros.stdint_macros)
+add_header(EFI_VIRTUAL_ADDRESS HDR EFI_VIRTUAL_ADDRESS.h DEPENDS libc.include.llvm-libc-macros.stdint_macros)
+
+add_header(EFI_MEMORY_DESCRIPTOR
+ HDR
+ EFI_MEMORY_DESCRIPTOR.h
+ DEPENDS
+ libc.include.llvm-libc-macros.stdint_macros
+ .EFI_PHYSICAL_ADDRESS
+ .EFI_VIRTUAL_ADDRESS
+)
+
+add_header(EFI_ALLOCATE_TYPE HDR EFI_ALLOCATE_TYPE.h)
+add_header(EFI_EVENT HDR EFI_EVENT.h)
+add_header(EFI_INTERFACE_TYPE HDR EFI_INTERFACE_TYPE.h)
+add_header(EFI_LOCATE_SEARCH_TYPE HDR EFI_LOCATE_SEARCH_TYPE.h)
+add_header(EFI_MEMORY_TYPE HDR EFI_MEMORY_TYPE.h)
+add_header(EFI_HANDLE HDR EFI_HANDLE.h)
+add_header(EFI_TIME HDR EFI_TIME.h DEPENDS libc.include.llvm-libc-macros.stdint_macros)
+add_header(EFI_TIMER_DELAY HDR EFI_TIMER_DELAY.h)
+add_header(EFI_TPL HDR EFI_TPL.h DEPENDS .size_t)
+add_header(EFI_STATUS HDR EFI_STATUS.h DEPENDS .size_t)
+
+add_header(EFI_OPEN_PROTOCOL_INFORMATION_ENTRY
+ HDR
+ EFI_OPEN_PROTOCOL_INFORMATION_ENTRY.h
+ DEPENDS
+ libc.include.llvm-libc-macros.stdint_macros
+ .EFI_HANDLE
+)
+
+add_header(EFI_CAPSULE
+ HDR
+ EFI_CAPSULE.h
+ DEPENDS
+ libc.include.llvm-libc-macros.stdint_macros
...
[truncated]
|
✅ With the latest revision this PR passed the C/C++ code formatter. |
26a24f4
to
a9d4c26
Compare
#include "EFI_TIMER_DELAY.h" | ||
#include "EFI_TPL.h" | ||
#include "char16_t.h" | ||
#include "include/llvm-libc-macros/EFIAPI-macros.h" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
use relative paths to include other headers inside libc/include/...
because they might be copied over to other places.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
#include "EFI_TABLE_HEADER.h" | ||
#include "EFI_TIME.h" | ||
#include "char16_t.h" | ||
#include "include/llvm-libc-macros/EFIAPI-macros.h" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
use relative path.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
a9d4c26
to
ab016f6
Compare
@@ -69,6 +69,10 @@ function(get_arch_and_system_from_triple triple arch_var sys_var) | |||
set(target_sys "darwin") | |||
endif() | |||
|
|||
if(target_sys STREQUAL "unknown") | |||
list(GET triple_comps -1 target_sys) | |||
endif() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure if this is completely valid since someone could use aarch64-unknown-uefi-llvm
as a valid triple to describe this toolchain.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Probably making it 2 instead of -1 would work for that. I just tested it with 2 using aarch64-unknown-uefi
and nothing broke.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
uefi
in this case should pretty easily replace linux
, can we not use the same handling?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure I follow what you mean.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
aarch64-unknown-linux-llvm
and aarch64-unknown-uefi-llvm
should be able to use the exact same parsing less a single string compare.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, since they both match on unknown. It would just shift to the 3rd component.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm just trying to figure out why this is necessary for the UEFI case but not the Linux case.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure either, it was setting LLVM_TARGET_OS
to unknown before the change.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe the lack of the ABI in the triple freaks it out? Man I hate github code reviews, can't even comment on related lines of code.
string(REPLACE "-" ";" triple_comps ${triple})
list(LENGTH triple_comps triple_size)
if(triple_size LESS "3")
return()
return()
endif()
math(EXPR system_index "${triple_size} - 2")
list(GET triple_comps 0 target_arch)
Likely it just gets confused with a triple of size three and indexes into the system. Honestly it should probably just take the third element here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh that's possible, though it probably is still good to have this change. Maybe we should rework that function at a later time to properly accept doubles ($arch-$os
), triple ($arch-$vendor-$os
), and the full tuple ($arch-$vendor-$os-$abi
). The function feels a little over engineered.
786f34f
to
220fd07
Compare
Prints almost works:
#include <stdio.h>
int main() {
return puts("Hello\r\n");
} |
565c5b9
to
21585ba
Compare
CC @Prabhuk I have discovered an issue which may be worth investigating. Even though |
Thanks for experimenting with the current state of the UEFI toolchain. If I am not mistaken we will need to land the backend necessary in LLVM for this to work. I have changes for X86_64 backend at #109320 which I want to land after your #120632 lands. I imagine we would require similar but hopefully much easier to deal with Aarch64 backend changes in LLVM as well for your experiment to work. Please let me know if my understanding here is not correct. |
Yeah, that sounds good. I'll give things another try once we have those PR's merged. |
I am going to work on that right after Christmas break. Hopefully I can make the draft PR #109320 available for review by end of the week. |
set(TARGET_LIBC_ENTRYPOINTS | ||
libc.src.compiler.__stack_chk_fail | ||
|
||
# ctype.h entrypoints |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do these all pass tests? It's probably best to start with a really minimal set and then add the entrypoints / headers as we get support in a follow-up
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tests don't quite build from what I can tell
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, tests build now and run! To run tests, run ninja check-libc
and let it fail executing on the host. Next, cd into the directory containing a set (include
or src
under libc/test
). Collect the tests like this:
find . -type f -name 'libc.test.*__hermetic__.__build__' | tr '/' '\\' > startup.nsh
Then pass the directory you are in to QEMU, example:
qemu-system-aarch64 -machine virt,gic-version=max,accel=kvm:tcg -cpu max -drive if=pflash,format=raw,unit=0,readonly=on,file=/nix/store/i3d83jqxl2w85p720f88ymdxwlpaz9vf-OVMF-202408.01-fd/FV/AAVMF_CODE.fd -serial stdio -m 4G -drive file=fat:rw:/home/ross/llvm-project/runtimes/build/libc/test/include,format=raw,media=disk
Now all tests will run.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We now have a test driver in libc/testing/scripts/uefi_runner.py
. To use it, install OVMF for the system you're compiling for. Arch Linux has edk2-ovmf
and NixOS has pkgs.OVMF
. Just set CMAKE_CROSSCOMPILING_EMULATOR
to the script. If OVMF is not at the path the script expects, use $OVMF_PATH
to set it to the directory it exists at.
52df600
to
f52cd3e
Compare
d369bf6
to
c0211ab
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a beast of a patch, would probably be easier if we just enabled the minimal set of entrypoints necessary to run tests and then added everything else.
@@ -605,6 +605,7 @@ function(add_integration_test test_name) | |||
${INTEGRATION_TEST_ENV} | |||
$<$<BOOL:${LIBC_TARGET_OS_IS_GPU}>:${gpu_loader_exe}> | |||
${CMAKE_CROSSCOMPILING_EMULATOR} | |||
$<$<BOOL:${LIBC_TARGET_OS_IS_UEFI}>:${LIBC_TARGET_TRIPLE}> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is this doing? This line is supposed to define the 'emulator, so I'm guessing intentionally that this will run
x86_64-unknown-uefi-gnu test.exe`?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It adds the target triplet for the test runner.
@@ -673,6 +674,7 @@ function(add_libc_hermetic test_name) | |||
libc.src.string.memset | |||
libc.src.strings.bcmp | |||
libc.src.strings.bzero | |||
libc.src.stdlib.atexit |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The list here is for libcalls that the compiler specifically exports, however we do need atexit
. Normally this is a dependency on the startup
object so it gets picked up.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, for whatever reason that I can't remember I needed to add it for the tests to compile.
@@ -736,6 +738,11 @@ function(add_libc_hermetic test_name) | |||
endif() | |||
endforeach() | |||
|
|||
if(LIBC_TARGET_OS_IS_UEFI) | |||
target_link_options(${fq_build_target_name} PRIVATE | |||
${LIBC_COMPILE_OPTIONS_DEFAULT} "-Wl,/lldmingw") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I feel like that's not the proper solution, though I don't know off the top of my head why symbols would be missing. I'd think that lld-link
wouldn't have the static library ordering thing that GNU linkers have. IF that's the case then it would be easier to just prepend the linker arguments with --whole-archive
or whatever the lld-link
equivalent is. (I think there's a per-static library version we could use when building the test list.)
DEPENDS | ||
.${LIBC_TARGET_OS}.remove | ||
) | ||
if(NOT LIBC_TARGET_OS_IS_UEFI) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is this necessary? If these cannot be used then don't enable them in the entrypoints list.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't remember, I don't even have them in the entrypoints list and I had to remove them when I was trying to get tests building.
libc/test/UnitTest/CMakeLists.txt
Outdated
@@ -25,7 +25,8 @@ function(add_unittest_framework_library name) | |||
endif() | |||
endforeach() | |||
|
|||
if(LLVM_LIBC_FULL_BUILD) | |||
# UEFI requires full builds | |||
if(LLVM_LIBC_FULL_BUILD AND NOT LIBC_TARGET_OS_IS_UEFI) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should probably just have this set to ON when we setup the UEFI target like the GPU.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So not have the UEFI condition? It's needed because without it, tests fail to build.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Misread this due to the comment, I thought it was just requiring full build. The GPU project also disables unit tests so it should be the same handling.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So then this condition isn't necessary?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
set(LIBC_ENABLE_UNITTESTS OFF)
should be all that's needed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, well that's good. I'll get that here in a second, I think it's one of those things I tried while iterating and forgot to drop that specific change.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, I've dropped the UEFI conditional
#include "src/__support/macros/properties/types.h" // LIBC_TYPES_HAS_INT128 | ||
#include "src/__support/uint128.h" | ||
#include "test/UnitTest/TestLogger.h" | ||
|
||
#ifndef LIBC_TARGET_OS_IS_UEFI |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we not define clock()
? Does UEFI not have access to a counter?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fun fact, someone seems to have added Aarch64 support for __builtin_readsteadycounter
https://godbolt.org/z/qK3341xYn.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's the system time which isn't in a super friendly format. But I don't think there's an actual system clock as defined in the spec.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah disregard, forgot that xzr
is the zero register so it's just falling back to the default. For clock
the only thing that matters is ticks and a tickrate, so if there's some way to get that you can implement clock and MONOTONIC CLOCK.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could implement a clock but it'd be platform specific. We'd have to have code for the PIC, HPIC, & APIC on x86.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I just found out there is GetNextMonotonicCount
in the boot services.
I agree, I started reviewing this change but it's too big to review in its entirety, especially as the implementation keeps evolving. There are also several parts of this change that I think will require further discussion (preferably on Discourse or at LLVM libc monthly meeting), and some might require further changes to the Clang driver. I would suggest breaking up this change into a series of smaller PRs which is a good software engineering practice. The first PR would ideally be just the minimal build support necessary to build an empty C program (this is actually what the description of this PR says but the actual implementation is much larger). Every feature should then have its own PR, the smaller the better. |
Closing in favor of multiple PR's. |
Originated from #120687 This PR simply adds the necessary headers for UEFI which defines all the necessary types. This PR unlocks the ability to work on other PR's for UEFI support.
Originated from llvm#120687 This PR simply adds the necessary headers for UEFI which defines all the necessary types. This PR unlocks the ability to work on other PR's for UEFI support.
Not even a hello world can run yet but this adds in all the necessary files and makes the necessary changes to start with UEFI. With #120632 being used along side this PR, I can generate a simple empty main program. This uses the triples
aarch64-unknown-uefi
andx86_64-unknown-uefi
.Testing can be done by running something like this:
Based on the UEFI 2.10 spec.