[libc-commits] [libc] 865fb9c - [libc][uefi] add crt1 (#132150)
via libc-commits
libc-commits at lists.llvm.org
Fri May 9 09:02:36 PDT 2025
Author: Tristan Ross
Date: 2025-05-09T09:02:33-07:00
New Revision: 865fb9c1a50f8b836a8c9ee6f4d1cbe7cce59fc3
URL: https://github.com/llvm/llvm-project/commit/865fb9c1a50f8b836a8c9ee6f4d1cbe7cce59fc3
DIFF: https://github.com/llvm/llvm-project/commit/865fb9c1a50f8b836a8c9ee6f4d1cbe7cce59fc3.diff
LOG: [libc][uefi] add crt1 (#132150)
Adds `crt1.o` for the UEFI platform in the LLVM C library. This makes
things start to become useful.
Added:
libc/config/uefi/app.h
libc/src/__support/OSUtil/uefi/error.h
libc/startup/uefi/CMakeLists.txt
libc/startup/uefi/crt1.cpp
libc/test/integration/startup/uefi/CMakeLists.txt
libc/test/integration/startup/uefi/main_without_args.cpp
Modified:
libc/config/app.h
libc/include/CMakeLists.txt
libc/include/Uefi.yaml
libc/include/llvm-libc-types/CMakeLists.txt
libc/include/llvm-libc-types/EFI_STATUS.h
libc/src/__support/OSUtil/uefi/CMakeLists.txt
libc/src/__support/OSUtil/uefi/exit.cpp
libc/src/__support/OSUtil/uefi/io.cpp
Removed:
libc/include/Uefi.h.def
################################################################################
diff --git a/libc/config/app.h b/libc/config/app.h
index 27f4141d80c4b..e9206c7242250 100644
--- a/libc/config/app.h
+++ b/libc/config/app.h
@@ -15,6 +15,8 @@
#include "gpu/app.h"
#elif defined(__linux__)
#include "linux/app.h"
+#elif defined(__UEFI__)
+#include "uefi/app.h"
#endif
#endif // LLVM_LIBC_CONFIG_APP_H
diff --git a/libc/config/uefi/app.h b/libc/config/uefi/app.h
new file mode 100644
index 0000000000000..0374a47ba3402
--- /dev/null
+++ b/libc/config/uefi/app.h
@@ -0,0 +1,34 @@
+//===-- Classes to capture properites of UEFI applications ------*- C++ -*-===//
+//
+// 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_CONFIG_UEFI_APP_H
+#define LLVM_LIBC_CONFIG_UEFI_APP_H
+
+#include "include/llvm-libc-types/EFI_HANDLE.h"
+#include "include/llvm-libc-types/EFI_SYSTEM_TABLE.h"
+#include "src/__support/macros/config.h"
+#include "src/__support/macros/properties/architectures.h"
+
+#include <stdint.h>
+
+namespace LIBC_NAMESPACE_DECL {
+
+// Data structure which captures properties of a UEFI application.
+struct AppProperties {
+ // UEFI system table
+ EFI_SYSTEM_TABLE *system_table;
+
+ // UEFI image handle
+ EFI_HANDLE image_handle;
+};
+
+[[gnu::weak]] extern AppProperties app;
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_CONFIG_UEFI_APP_H
diff --git a/libc/include/CMakeLists.txt b/libc/include/CMakeLists.txt
index e407de2f16959..7209e10c68b8f 100644
--- a/libc/include/CMakeLists.txt
+++ b/libc/include/CMakeLists.txt
@@ -741,7 +741,6 @@ add_header_macro(
add_header_macro(
uefi
../libc/include/Uefi.yaml
- Uefi.h.def
Uefi.h
DEPENDS
.llvm_libc_common_h
diff --git a/libc/include/Uefi.yaml b/libc/include/Uefi.yaml
index 9f38ff3f4a497..72b50ed724660 100644
--- a/libc/include/Uefi.yaml
+++ b/libc/include/Uefi.yaml
@@ -9,8 +9,4 @@ types:
- type_name: EFI_SYSTEM_TABLE
enums: []
functions: []
-objects:
- - object_name: efi_system_table
- object_type: EFI_SYSTEM_TABLE *
- - object_name: efi_image_handle
- object_type: EFI_HANDLE
+objects: []
diff --git a/libc/include/llvm-libc-types/CMakeLists.txt b/libc/include/llvm-libc-types/CMakeLists.txt
index 26a3ed06b6f05..b24c97301668a 100644
--- a/libc/include/llvm-libc-types/CMakeLists.txt
+++ b/libc/include/llvm-libc-types/CMakeLists.txt
@@ -186,7 +186,7 @@ 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_STATUS HDR EFI_STATUS.h DEPENDS libc.include.llvm-libc-macros.stdint_macros)
add_header(EFI_OPEN_PROTOCOL_INFORMATION_ENTRY
HDR
diff --git a/libc/include/llvm-libc-types/EFI_STATUS.h b/libc/include/llvm-libc-types/EFI_STATUS.h
index f7fa6e52381e1..bb9542bed8efc 100644
--- a/libc/include/llvm-libc-types/EFI_STATUS.h
+++ b/libc/include/llvm-libc-types/EFI_STATUS.h
@@ -9,8 +9,52 @@
#ifndef LLVM_LIBC_TYPES_EFI_STATUS_H
#define LLVM_LIBC_TYPES_EFI_STATUS_H
-#include "size_t.h"
+#include "../llvm-libc-macros/stdint-macros.h"
-typedef size_t EFI_STATUS;
+typedef uintptr_t EFI_STATUS;
+
+#define EFI_SUCCESS 0
+
+#define EFI_LOAD_ERROR 1
+#define EFI_INVALID_PARAMETER 2
+#define EFI_UNSUPPORTED 3
+#define EFI_BAD_BUFFER_SIZE 4
+#define EFI_BUFFER_TOO_SMALL 5
+#define EFI_NOT_READY 6
+#define EFI_DEVICE_ERROR 7
+#define EFI_WRITE_PROTECTED 8
+#define EFI_OUT_OF_RESOURCES 9
+#define EFI_VOLUME_CORRUPTED 10
+#define EFI_VOLUME_FULL 11
+#define EFI_NO_MEDIA 12
+#define EFI_MEDIA_CHANGED 13
+#define EFI_NOT_FOUND 14
+#define EFI_ACCESS_DENIED 15
+#define EFI_NO_RESPONSE 16
+#define EFI_NO_MAPPING 17
+#define EFI_TIMEOUT 18
+#define EFI_NOT_STARTED 19
+#define EFI_ALREADY_STARTED 20
+#define EFI_ABORTED 21
+#define EFI_ICMP_ERROR 22
+#define EFI_TFTP_ERROR 23
+#define EFI_PROTOCOL_ERROR 24
+#define EFI_INCOMPATIBLE_VERSION 25
+#define EFI_SECURITY_VIOLATION 26
+#define EFI_CRC_ERROR 27
+#define EFI_END_OF_MEDIA 28
+#define EFI_END_OF_FILE 31
+#define EFI_INVALID_LANGUAGE 32
+#define EFI_COMPROMISED_DATA 33
+#define EFI_IP_ADDRESS_CONFLICT 34
+#define EFI_HTTP_ERROR 35
+
+#define EFI_WARN_UNKNOWN_GLYPH 1
+#define EFI_WARN_DELETE_FAILURE 2
+#define EFI_WARN_WRITE_FAILURE 3
+#define EFI_WARN_BUFFER_TOO_SMALL 4
+#define EFI_WARN_STALE_DATA 5
+#define EFI_WARN_FILE_SYSTEM 6
+#define EFI_WARN_RESET_REQUIRED 7
#endif // LLVM_LIBC_TYPES_EFI_STATUS_H
diff --git a/libc/src/__support/OSUtil/uefi/CMakeLists.txt b/libc/src/__support/OSUtil/uefi/CMakeLists.txt
index 79ec8ab602456..b8b785a6a0c28 100644
--- a/libc/src/__support/OSUtil/uefi/CMakeLists.txt
+++ b/libc/src/__support/OSUtil/uefi/CMakeLists.txt
@@ -6,6 +6,8 @@ add_object_library(
HDRS
io.h
DEPENDS
+ libc.config.app_h
+ libc.include.llvm-libc-types.EFI_SYSTEM_TABLE
libc.src.__support.common
libc.src.__support.CPP.string_view
)
diff --git a/libc/src/__support/OSUtil/uefi/error.h b/libc/src/__support/OSUtil/uefi/error.h
new file mode 100644
index 0000000000000..9fdc569bab574
--- /dev/null
+++ b/libc/src/__support/OSUtil/uefi/error.h
@@ -0,0 +1,104 @@
+//===----------- UEFI implementation of error utils --------------*- C++-*-===//
+//
+// 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_SRC___SUPPORT_OSUTIL_UEFI_ERROR_H
+#define LLVM_LIBC_SRC___SUPPORT_OSUTIL_UEFI_ERROR_H
+
+#include "hdr/errno_macros.h"
+#include "include/llvm-libc-types/EFI_STATUS.h"
+#include "src/__support/CPP/array.h"
+#include "src/__support/CPP/limits.h"
+#include "src/__support/macros/attributes.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+static constexpr int EFI_ERROR_MAX_BIT = cpp::numeric_limits<EFI_STATUS>::max();
+
+static constexpr int EFI_ENCODE_ERROR(int value) {
+ return EFI_ERROR_MAX_BIT | (EFI_ERROR_MAX_BIT >> 2) | (value);
+}
+
+static constexpr int EFI_ENCODE_WARNING(int value) {
+ return (EFI_ERROR_MAX_BIT >> 2) | (value);
+}
+
+struct UefiStatusErrnoEntry {
+ EFI_STATUS status;
+ int errno_value;
+};
+
+static constexpr cpp::array<UefiStatusErrnoEntry, 43> UEFI_STATUS_ERRNO_MAP = {{
+ {EFI_SUCCESS, 0},
+ {EFI_ENCODE_ERROR(EFI_LOAD_ERROR), EINVAL},
+ {EFI_ENCODE_ERROR(EFI_INVALID_PARAMETER), EINVAL},
+ {EFI_ENCODE_ERROR(EFI_BAD_BUFFER_SIZE), EINVAL},
+ {EFI_ENCODE_ERROR(EFI_NOT_READY), EBUSY},
+ {EFI_ENCODE_ERROR(EFI_DEVICE_ERROR), EIO},
+ {EFI_ENCODE_ERROR(EFI_WRITE_PROTECTED), EPERM},
+ {EFI_ENCODE_ERROR(EFI_OUT_OF_RESOURCES), ENOMEM},
+ {EFI_ENCODE_ERROR(EFI_VOLUME_CORRUPTED), EROFS},
+ {EFI_ENCODE_ERROR(EFI_VOLUME_FULL), ENOSPC},
+ {EFI_ENCODE_ERROR(EFI_NO_MEDIA), ENODEV},
+ {EFI_ENCODE_ERROR(EFI_MEDIA_CHANGED), ENXIO},
+ {EFI_ENCODE_ERROR(EFI_NOT_FOUND), ENOENT},
+ {EFI_ENCODE_ERROR(EFI_ACCESS_DENIED), EACCES},
+ {EFI_ENCODE_ERROR(EFI_NO_RESPONSE), EBUSY},
+ {EFI_ENCODE_ERROR(EFI_NO_MAPPING), ENODEV},
+ {EFI_ENCODE_ERROR(EFI_TIMEOUT), EBUSY},
+ {EFI_ENCODE_ERROR(EFI_NOT_STARTED), EAGAIN},
+ {EFI_ENCODE_ERROR(EFI_ALREADY_STARTED), EINVAL},
+ {EFI_ENCODE_ERROR(EFI_ABORTED), EFAULT},
+ {EFI_ENCODE_ERROR(EFI_ICMP_ERROR), EIO},
+ {EFI_ENCODE_ERROR(EFI_TFTP_ERROR), EIO},
+ {EFI_ENCODE_ERROR(EFI_PROTOCOL_ERROR), EINVAL},
+ {EFI_ENCODE_ERROR(EFI_INCOMPATIBLE_VERSION), EINVAL},
+ {EFI_ENCODE_ERROR(EFI_SECURITY_VIOLATION), EPERM},
+ {EFI_ENCODE_ERROR(EFI_CRC_ERROR), EINVAL},
+ {EFI_ENCODE_ERROR(EFI_END_OF_MEDIA), EPIPE},
+ {EFI_ENCODE_ERROR(EFI_END_OF_FILE), EPIPE},
+ {EFI_ENCODE_ERROR(EFI_INVALID_LANGUAGE), EINVAL},
+ {EFI_ENCODE_ERROR(EFI_COMPROMISED_DATA), EINVAL},
+ {EFI_ENCODE_ERROR(EFI_IP_ADDRESS_CONFLICT), EINVAL},
+ {EFI_ENCODE_ERROR(EFI_HTTP_ERROR), EIO},
+ {EFI_ENCODE_WARNING(EFI_WARN_UNKNOWN_GLYPH), EINVAL},
+ {EFI_ENCODE_WARNING(EFI_WARN_DELETE_FAILURE), EROFS},
+ {EFI_ENCODE_WARNING(EFI_WARN_WRITE_FAILURE), EROFS},
+ {EFI_ENCODE_WARNING(EFI_WARN_BUFFER_TOO_SMALL), E2BIG},
+ {EFI_ENCODE_WARNING(EFI_WARN_STALE_DATA), EINVAL},
+ {EFI_ENCODE_WARNING(EFI_WARN_FILE_SYSTEM), EROFS},
+ {EFI_ENCODE_WARNING(EFI_WARN_RESET_REQUIRED), EINTR},
+}};
+
+LIBC_INLINE int uefi_status_to_errno(EFI_STATUS status) {
+ for (auto it = UEFI_STATUS_ERRNO_MAP.begin();
+ it != UEFI_STATUS_ERRNO_MAP.end(); it++) {
+ const struct UefiStatusErrnoEntry entry = *it;
+ if (entry.status == status)
+ return entry.errno_value;
+ }
+
+ // Unknown type
+ return EINVAL;
+}
+
+LIBC_INLINE EFI_STATUS errno_to_uefi_status(int errno_value) {
+ for (auto it = UEFI_STATUS_ERRNO_MAP.begin();
+ it != UEFI_STATUS_ERRNO_MAP.end(); it++) {
+ const struct UefiStatusErrnoEntry entry = *it;
+ if (entry.errno_value == errno_value)
+ return entry.status;
+ }
+
+ // Unknown type
+ return EFI_INVALID_PARAMETER;
+}
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_OSUTIL_UEFI_ERROR_H
diff --git a/libc/src/__support/OSUtil/uefi/exit.cpp b/libc/src/__support/OSUtil/uefi/exit.cpp
index 432f69a306b79..e734983cd125b 100644
--- a/libc/src/__support/OSUtil/uefi/exit.cpp
+++ b/libc/src/__support/OSUtil/uefi/exit.cpp
@@ -7,14 +7,16 @@
//===-----------------------------------------------------------------===//
#include "src/__support/OSUtil/exit.h"
-#include "include/Uefi.h"
+#include "config/uefi.h"
+#include "include/llvm-libc-types/EFI_SYSTEM_TABLE.h"
#include "src/__support/macros/config.h"
namespace LIBC_NAMESPACE_DECL {
namespace internal {
[[noreturn]] void exit(int status) {
- efi_system_table->BootServices->Exit(efi_image_handle, status, 0, nullptr);
+ app.system_table->BootServices->Exit(__llvm_libc_efi_image_handle, status, 0,
+ nullptr);
__builtin_unreachable();
}
diff --git a/libc/src/__support/OSUtil/uefi/io.cpp b/libc/src/__support/OSUtil/uefi/io.cpp
index 756c5aaf8f452..e1e50fbad3931 100644
--- a/libc/src/__support/OSUtil/uefi/io.cpp
+++ b/libc/src/__support/OSUtil/uefi/io.cpp
@@ -8,19 +8,24 @@
#include "io.h"
+#include "Uefi.h"
+#include "config/app.h"
#include "src/__support/CPP/string_view.h"
#include "src/__support/macros/config.h"
namespace LIBC_NAMESPACE_DECL {
-ssize_t read_from_stdin(char *buf, size_t size) { return 0; }
+ssize_t read_from_stdin([[gnu::unused]] char *buf,
+ [[gnu::unused]] size_t size) {
+ return 0;
+}
void write_to_stdout(cpp::string_view msg) {
// TODO: use mbstowcs once implemented
for (size_t i = 0; i < msg.size(); i++) {
char16_t e[2] = {msg[i], 0};
- efi_system_table->ConOut->OutputString(
- efi_system_table->ConOut, reinterpret_cast<const char16_t *>(&e));
+ app.system_table->ConOut->OutputString(
+ app.system_table->ConOut, reinterpret_cast<const char16_t *>(&e));
}
}
@@ -28,8 +33,8 @@ void write_to_stderr(cpp::string_view msg) {
// TODO: use mbstowcs once implemented
for (size_t i = 0; i < msg.size(); i++) {
char16_t e[2] = {msg[i], 0};
- efi_system_table->StdErr->OutputString(
- efi_system_table->StdErr, reinterpret_cast<const char16_t *>(&e));
+ app.system_table->StdErr->OutputString(
+ app.system_table->StdErr, reinterpret_cast<const char16_t *>(&e));
}
}
diff --git a/libc/startup/uefi/CMakeLists.txt b/libc/startup/uefi/CMakeLists.txt
new file mode 100644
index 0000000000000..2e6a993e77e30
--- /dev/null
+++ b/libc/startup/uefi/CMakeLists.txt
@@ -0,0 +1,50 @@
+# TODO: Use generic "add_startup_object" https://github.com/llvm/llvm-project/issues/133156
+function(add_startup_object name)
+ cmake_parse_arguments(
+ "ADD_STARTUP_OBJECT"
+ "ALIAS" # Option argument
+ "SRC" # Single value arguments
+ "DEPENDS;COMPILE_OPTIONS" # Multi value arguments
+ ${ARGN}
+ )
+
+ get_fq_target_name(${name} fq_target_name)
+ if(ADD_STARTUP_OBJECT_ALIAS)
+ get_fq_deps_list(fq_dep_list ${ADD_STARTUP_OBJECT_DEPENDS})
+ add_library(${fq_target_name} ALIAS ${fq_dep_list})
+ return()
+ endif()
+
+ add_object_library(
+ ${name}
+ SRCS ${ADD_STARTUP_OBJECT_SRC}
+ COMPILE_OPTIONS ${ADD_STARTUP_OBJECT_COMPILE_OPTIONS}
+ ${ADD_STARTUP_OBJECT_UNPARSED_ARGUMENTS}
+ DEPENDS ${ADD_STARTUP_OBJECT_DEPENDS}
+ )
+ set_target_properties(
+ ${fq_target_name}
+ PROPERTIES
+ OUTPUT_NAME ${name}.o
+ )
+endfunction()
+
+add_startup_object(
+ crt1
+ SRCS
+ crt1.cpp
+ DEPENDS
+ libc.config.app_h
+ libc.src.__support.OSUtil.uefi.uefi_util
+)
+
+add_custom_target(libc-startup)
+set(startup_components crt1)
+foreach(target IN LISTS startup_components)
+ set(fq_target_name libc.startup.uefi.${target})
+ add_dependencies(libc-startup ${fq_target_name})
+ install(FILES $<TARGET_OBJECTS:${fq_target_name}>
+ DESTINATION ${LIBC_INSTALL_LIBRARY_DIR}
+ RENAME $<TARGET_PROPERTY:${fq_target_name},OUTPUT_NAME>
+ COMPONENT libc)
+endforeach()
diff --git a/libc/startup/uefi/crt1.cpp b/libc/startup/uefi/crt1.cpp
new file mode 100644
index 0000000000000..6883a88ff1c30
--- /dev/null
+++ b/libc/startup/uefi/crt1.cpp
@@ -0,0 +1,32 @@
+//===-- Implementation of crt for UEFI ------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "config/app.h"
+#include "include/llvm-libc-types/EFI_STATUS.h"
+#include "src/__support/OSUtil/uefi/error.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+AppProperties app;
+}
+
+extern "C" {
+EFI_HANDLE __llvm_libc_efi_image_handle;
+EFI_SYSTEM_TABLE *__llvm_libc_efi_system_table;
+
+int main(int argc, char **argv, char **envp);
+
+EFI_STATUS EfiMain(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable) {
+ LIBC_NAMESPACE::app.image_handle = ImageHandle;
+ LIBC_NAMESPACE::app.system_table = SystemTable;
+
+ // TODO: we need the EFI_SHELL_PROTOCOL, malloc, free, and UTF16 -> UTF8
+ // conversion.
+ return LIBC_NAMESPACE::errno_to_uefi_status(main(0, nullptr, nullptr));
+}
+}
diff --git a/libc/test/integration/startup/uefi/CMakeLists.txt b/libc/test/integration/startup/uefi/CMakeLists.txt
new file mode 100644
index 0000000000000..cb43dcb31ddf8
--- /dev/null
+++ b/libc/test/integration/startup/uefi/CMakeLists.txt
@@ -0,0 +1,9 @@
+add_custom_target(libc-startup-tests)
+add_dependencies(libc-integration-tests libc-startup-tests)
+
+add_integration_test(
+ startup_no_args_test
+ SUITE libc-startup-tests
+ SRCS
+ main_without_args.cpp
+)
diff --git a/libc/include/Uefi.h.def b/libc/test/integration/startup/uefi/main_without_args.cpp
similarity index 58%
rename from libc/include/Uefi.h.def
rename to libc/test/integration/startup/uefi/main_without_args.cpp
index 6655e13579cd8..9bc3546aeb123 100644
--- a/libc/include/Uefi.h.def
+++ b/libc/test/integration/startup/uefi/main_without_args.cpp
@@ -1,4 +1,4 @@
-//===-- UEFI header uefi.h --------------------------------------------------===//
+//===-- Loader test for main without args ---------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@@ -6,11 +6,6 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_LIBC_UEFI_H
-#define LLVM_LIBC_UEFI_H
+#include "test/IntegrationTest/test.h"
-#include "__llvm-libc-common.h"
-
-%%public_api()
-
-#endif // LLVM_LIBC_UEFI_H
+TEST_MAIN() { return 0; }
More information about the libc-commits
mailing list