Skip to content
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

Open
wants to merge 13 commits into
base: main
Choose a base branch
from

Conversation

RossComputerGuy
Copy link
Contributor

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 and x86_64-unknown-uefi.

Testing can be done by running something like this:

clang-20 -target aarch64-uefi a.c -Ilibc/include/ -Blibc/lib libc/startup/uefi/CMakeFiles//libc.startup.uefi.crt1.dir/crt1.cpp.o

Based on the UEFI 2.10 spec.

@llvmbot llvmbot added the libc label Dec 20, 2024
@llvmbot
Copy link
Member

llvmbot commented Dec 20, 2024

@llvm/pr-subscribers-libc

Author: Tristan Ross (RossComputerGuy)

Changes

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 and x86_64-unknown-uefi.

Testing can be done by running something like this:

clang-20 -target aarch64-uefi a.c -Ilibc/include/ -Blibc/lib libc/startup/uefi/CMakeFiles//libc.startup.uefi.crt1.dir/crt1.cpp.o

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:

  • (modified) libc/cmake/modules/LLVMLibCArchitectures.cmake (+6)
  • (added) libc/config/uefi/config.json (+29)
  • (added) libc/config/uefi/entrypoints.txt (+450)
  • (added) libc/config/uefi/headers.txt (+20)
  • (added) libc/hdrgen/yaml/Uefi.yaml (+11)
  • (modified) libc/include/CMakeLists.txt (+17)
  • (added) libc/include/Uefi.h.def (+16)
  • (modified) libc/include/llvm-libc-macros/CMakeLists.txt (+6)
  • (added) libc/include/llvm-libc-macros/EFIAPI-macros.h (+10)
  • (modified) libc/include/llvm-libc-types/CMakeLists.txt (+121)
  • (added) libc/include/llvm-libc-types/EFI_ALLOCATE_TYPE.h (+19)
  • (added) libc/include/llvm-libc-types/EFI_BOOT_SERVICES.h (+249)
  • (added) libc/include/llvm-libc-types/EFI_CAPSULE.h (+26)
  • (added) libc/include/llvm-libc-types/EFI_CONFIGURATION_TABLE.h (+19)
  • (added) libc/include/llvm-libc-types/EFI_DEVICE_PATH_PROTOCOL.h (+27)
  • (added) libc/include/llvm-libc-types/EFI_EVENT.h (+21)
  • (added) libc/include/llvm-libc-types/EFI_GUID.h (+21)
  • (added) libc/include/llvm-libc-types/EFI_HANDLE.h (+14)
  • (added) libc/include/llvm-libc-types/EFI_INTERFACE_TYPE.h (+16)
  • (added) libc/include/llvm-libc-types/EFI_LOCATE_SEARCH_TYPE.h (+18)
  • (added) libc/include/llvm-libc-types/EFI_MEMORY_DESCRIPTOR.h (+43)
  • (added) libc/include/llvm-libc-types/EFI_MEMORY_TYPE.h (+32)
  • (added) libc/include/llvm-libc-types/EFI_OPEN_PROTOCOL_INFORMATION_ENTRY.h (+22)
  • (added) libc/include/llvm-libc-types/EFI_PHYSICAL_ADDRESS.h (+16)
  • (added) libc/include/llvm-libc-types/EFI_RUNTIME_SERVICES.h (+134)
  • (added) libc/include/llvm-libc-types/EFI_SIMPLE_TEXT_INPUT_PROTOCOL.h (+41)
  • (added) libc/include/llvm-libc-types/EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.h (+68)
  • (added) libc/include/llvm-libc-types/EFI_STATUS.h (+16)
  • (added) libc/include/llvm-libc-types/EFI_SYSTEM_TABLE.h (+63)
  • (added) libc/include/llvm-libc-types/EFI_TABLE_HEADER.h (+22)
  • (added) libc/include/llvm-libc-types/EFI_TIME.h (+37)
  • (added) libc/include/llvm-libc-types/EFI_TIMER_DELAY.h (+18)
  • (added) libc/include/llvm-libc-types/EFI_TPL.h (+21)
  • (added) libc/include/llvm-libc-types/EFI_VIRTUAL_ADDRESS.h (+16)
  • (added) libc/include/uefi/CMakeLists.txt ()
  • (added) libc/include/uefi/status.h.def (+16)
  • (modified) libc/src/__support/OSUtil/io.h (+2)
  • (added) libc/src/__support/OSUtil/uefi/CMakeLists.txt (+11)
  • (added) libc/src/__support/OSUtil/uefi/exit.cpp (+23)
  • (added) libc/src/__support/OSUtil/uefi/io.cpp (+30)
  • (added) libc/src/__support/OSUtil/uefi/io.h (+25)
  • (modified) libc/src/stdio/CMakeLists.txt (+1-1)
  • (added) libc/src/stdio/uefi/CMakeLists.txt ()
  • (added) libc/startup/uefi/CMakeLists.txt (+56)
  • (added) libc/startup/uefi/crt1.cpp (+24)
  • (modified) libc/test/src/__support/CMakeLists.txt (+2-2)
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]

Copy link

github-actions bot commented Dec 20, 2024

✅ With the latest revision this PR passed the C/C++ code formatter.

@RossComputerGuy RossComputerGuy force-pushed the feat/libc-uefi-stage1 branch 2 times, most recently from 26a24f4 to a9d4c26 Compare December 20, 2024 07:01
#include "EFI_TIMER_DELAY.h"
#include "EFI_TPL.h"
#include "char16_t.h"
#include "include/llvm-libc-macros/EFIAPI-macros.h"
Copy link
Contributor

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.

Copy link
Contributor Author

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"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use relative path.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

@@ -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()
Copy link
Contributor

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.

Copy link
Contributor Author

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.

Copy link
Contributor

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?

Copy link
Contributor Author

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.

Copy link
Contributor

@jhuber6 jhuber6 Dec 20, 2024

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.

Copy link
Contributor Author

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.

Copy link
Contributor

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.

Copy link
Contributor Author

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.

Copy link
Contributor

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

Copy link
Contributor Author

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.

@RossComputerGuy RossComputerGuy force-pushed the feat/libc-uefi-stage1 branch 2 times, most recently from 786f34f to 220fd07 Compare December 20, 2024 16:42
@RossComputerGuy
Copy link
Contributor Author

Prints almost works:

clang-20 a.c -target aarch64-uefi -o uefi/a.efi -B fakeroot/var/empty/local/lib/ -I fakeroot/var/empty/local/include/ fakeroot/var/empty/local/lib/crt1.o libc/src/stdio/uefi/CMakeFiles/libc.src.stdio.uefi.puts.dir/puts.cpp.o libc/src/__support/UEFI/CMakeFiles/libc.src.__support.UEFI.file.dir/file.cpp.o  libc/src/string/CMakeFiles/libc.src.string.strlen.dir/strlen.cpp.o
Shell> FS0:
FS0:\> a.efi
Hlo
#include <stdio.h>

int main() {
  return puts("Hello\r\n");
}

@RossComputerGuy RossComputerGuy force-pushed the feat/libc-uefi-stage1 branch 2 times, most recently from 2babe0c to 2f7a61f Compare December 20, 2024 23:56
@RossComputerGuy
Copy link
Contributor Author

CC @Prabhuk

I have discovered an issue which may be worth investigating. Even though libc.a has symbols which the a.c above can use exists, it still says there's undefined symbols. It only exists when adding the .a files for those symbols into the clang call. Note that this testing is done only with #120632 applied and it looks like lld-link might be the culprit.

@Prabhuk
Copy link
Contributor

Prabhuk commented Dec 23, 2024

CC @Prabhuk

I have discovered an issue which may be worth investigating. Even though libc.a has symbols which the a.c above can use exists, it still says there's undefined symbols. It only exists when adding the .a files for those symbols into the clang call. Note that this testing is done only with #120632 applied and it looks like lld-link might be the culprit.

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.

@RossComputerGuy
Copy link
Contributor Author

Yeah, that sounds good. I'll give things another try once we have those PR's merged.

@Prabhuk
Copy link
Contributor

Prabhuk commented Dec 24, 2024

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.

@RossComputerGuy
Copy link
Contributor Author

Sounds good, #120632 is ready and once #109320 is merged along side with mine then I think the backend should be in a good state. I'm not sure if aarch64 would still have the linker problem though.

set(TARGET_LIBC_ENTRYPOINTS
libc.src.compiler.__stack_chk_fail

# ctype.h entrypoints
Copy link
Contributor

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

Copy link
Contributor Author

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

@RossComputerGuy RossComputerGuy force-pushed the feat/libc-uefi-stage1 branch 5 times, most recently from 52df600 to f52cd3e Compare December 24, 2024 16:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants