Skip to content

Commit 865fb9c

Browse files
[libc][uefi] add crt1 (llvm#132150)
Adds `crt1.o` for the UEFI platform in the LLVM C library. This makes things start to become useful.
1 parent 0077d4c commit 865fb9c

File tree

14 files changed

+298
-24
lines changed

14 files changed

+298
-24
lines changed

libc/config/app.h

+2
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
#include "gpu/app.h"
1616
#elif defined(__linux__)
1717
#include "linux/app.h"
18+
#elif defined(__UEFI__)
19+
#include "uefi/app.h"
1820
#endif
1921

2022
#endif // LLVM_LIBC_CONFIG_APP_H

libc/config/uefi/app.h

+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
//===-- Classes to capture properites of UEFI applications ------*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#ifndef LLVM_LIBC_CONFIG_UEFI_APP_H
10+
#define LLVM_LIBC_CONFIG_UEFI_APP_H
11+
12+
#include "include/llvm-libc-types/EFI_HANDLE.h"
13+
#include "include/llvm-libc-types/EFI_SYSTEM_TABLE.h"
14+
#include "src/__support/macros/config.h"
15+
#include "src/__support/macros/properties/architectures.h"
16+
17+
#include <stdint.h>
18+
19+
namespace LIBC_NAMESPACE_DECL {
20+
21+
// Data structure which captures properties of a UEFI application.
22+
struct AppProperties {
23+
// UEFI system table
24+
EFI_SYSTEM_TABLE *system_table;
25+
26+
// UEFI image handle
27+
EFI_HANDLE image_handle;
28+
};
29+
30+
[[gnu::weak]] extern AppProperties app;
31+
32+
} // namespace LIBC_NAMESPACE_DECL
33+
34+
#endif // LLVM_LIBC_CONFIG_UEFI_APP_H

libc/include/CMakeLists.txt

-1
Original file line numberDiff line numberDiff line change
@@ -741,7 +741,6 @@ add_header_macro(
741741
add_header_macro(
742742
uefi
743743
../libc/include/Uefi.yaml
744-
Uefi.h.def
745744
Uefi.h
746745
DEPENDS
747746
.llvm_libc_common_h

libc/include/Uefi.yaml

+1-5
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,4 @@ types:
99
- type_name: EFI_SYSTEM_TABLE
1010
enums: []
1111
functions: []
12-
objects:
13-
- object_name: efi_system_table
14-
object_type: EFI_SYSTEM_TABLE *
15-
- object_name: efi_image_handle
16-
object_type: EFI_HANDLE
12+
objects: []

libc/include/llvm-libc-types/CMakeLists.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,7 @@ add_header(EFI_HANDLE HDR EFI_HANDLE.h)
186186
add_header(EFI_TIME HDR EFI_TIME.h DEPENDS libc.include.llvm-libc-macros.stdint_macros)
187187
add_header(EFI_TIMER_DELAY HDR EFI_TIMER_DELAY.h)
188188
add_header(EFI_TPL HDR EFI_TPL.h DEPENDS .size_t)
189-
add_header(EFI_STATUS HDR EFI_STATUS.h DEPENDS .size_t)
189+
add_header(EFI_STATUS HDR EFI_STATUS.h DEPENDS libc.include.llvm-libc-macros.stdint_macros)
190190

191191
add_header(EFI_OPEN_PROTOCOL_INFORMATION_ENTRY
192192
HDR

libc/include/llvm-libc-types/EFI_STATUS.h

+46-2
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,52 @@
99
#ifndef LLVM_LIBC_TYPES_EFI_STATUS_H
1010
#define LLVM_LIBC_TYPES_EFI_STATUS_H
1111

12-
#include "size_t.h"
12+
#include "../llvm-libc-macros/stdint-macros.h"
1313

14-
typedef size_t EFI_STATUS;
14+
typedef uintptr_t EFI_STATUS;
15+
16+
#define EFI_SUCCESS 0
17+
18+
#define EFI_LOAD_ERROR 1
19+
#define EFI_INVALID_PARAMETER 2
20+
#define EFI_UNSUPPORTED 3
21+
#define EFI_BAD_BUFFER_SIZE 4
22+
#define EFI_BUFFER_TOO_SMALL 5
23+
#define EFI_NOT_READY 6
24+
#define EFI_DEVICE_ERROR 7
25+
#define EFI_WRITE_PROTECTED 8
26+
#define EFI_OUT_OF_RESOURCES 9
27+
#define EFI_VOLUME_CORRUPTED 10
28+
#define EFI_VOLUME_FULL 11
29+
#define EFI_NO_MEDIA 12
30+
#define EFI_MEDIA_CHANGED 13
31+
#define EFI_NOT_FOUND 14
32+
#define EFI_ACCESS_DENIED 15
33+
#define EFI_NO_RESPONSE 16
34+
#define EFI_NO_MAPPING 17
35+
#define EFI_TIMEOUT 18
36+
#define EFI_NOT_STARTED 19
37+
#define EFI_ALREADY_STARTED 20
38+
#define EFI_ABORTED 21
39+
#define EFI_ICMP_ERROR 22
40+
#define EFI_TFTP_ERROR 23
41+
#define EFI_PROTOCOL_ERROR 24
42+
#define EFI_INCOMPATIBLE_VERSION 25
43+
#define EFI_SECURITY_VIOLATION 26
44+
#define EFI_CRC_ERROR 27
45+
#define EFI_END_OF_MEDIA 28
46+
#define EFI_END_OF_FILE 31
47+
#define EFI_INVALID_LANGUAGE 32
48+
#define EFI_COMPROMISED_DATA 33
49+
#define EFI_IP_ADDRESS_CONFLICT 34
50+
#define EFI_HTTP_ERROR 35
51+
52+
#define EFI_WARN_UNKNOWN_GLYPH 1
53+
#define EFI_WARN_DELETE_FAILURE 2
54+
#define EFI_WARN_WRITE_FAILURE 3
55+
#define EFI_WARN_BUFFER_TOO_SMALL 4
56+
#define EFI_WARN_STALE_DATA 5
57+
#define EFI_WARN_FILE_SYSTEM 6
58+
#define EFI_WARN_RESET_REQUIRED 7
1559

1660
#endif // LLVM_LIBC_TYPES_EFI_STATUS_H

libc/src/__support/OSUtil/uefi/CMakeLists.txt

+2
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ add_object_library(
66
HDRS
77
io.h
88
DEPENDS
9+
libc.config.app_h
10+
libc.include.llvm-libc-types.EFI_SYSTEM_TABLE
911
libc.src.__support.common
1012
libc.src.__support.CPP.string_view
1113
)
+104
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
//===----------- UEFI implementation of error utils --------------*- C++-*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#ifndef LLVM_LIBC_SRC___SUPPORT_OSUTIL_UEFI_ERROR_H
10+
#define LLVM_LIBC_SRC___SUPPORT_OSUTIL_UEFI_ERROR_H
11+
12+
#include "hdr/errno_macros.h"
13+
#include "include/llvm-libc-types/EFI_STATUS.h"
14+
#include "src/__support/CPP/array.h"
15+
#include "src/__support/CPP/limits.h"
16+
#include "src/__support/macros/attributes.h"
17+
#include "src/__support/macros/config.h"
18+
19+
namespace LIBC_NAMESPACE_DECL {
20+
21+
static constexpr int EFI_ERROR_MAX_BIT = cpp::numeric_limits<EFI_STATUS>::max();
22+
23+
static constexpr int EFI_ENCODE_ERROR(int value) {
24+
return EFI_ERROR_MAX_BIT | (EFI_ERROR_MAX_BIT >> 2) | (value);
25+
}
26+
27+
static constexpr int EFI_ENCODE_WARNING(int value) {
28+
return (EFI_ERROR_MAX_BIT >> 2) | (value);
29+
}
30+
31+
struct UefiStatusErrnoEntry {
32+
EFI_STATUS status;
33+
int errno_value;
34+
};
35+
36+
static constexpr cpp::array<UefiStatusErrnoEntry, 43> UEFI_STATUS_ERRNO_MAP = {{
37+
{EFI_SUCCESS, 0},
38+
{EFI_ENCODE_ERROR(EFI_LOAD_ERROR), EINVAL},
39+
{EFI_ENCODE_ERROR(EFI_INVALID_PARAMETER), EINVAL},
40+
{EFI_ENCODE_ERROR(EFI_BAD_BUFFER_SIZE), EINVAL},
41+
{EFI_ENCODE_ERROR(EFI_NOT_READY), EBUSY},
42+
{EFI_ENCODE_ERROR(EFI_DEVICE_ERROR), EIO},
43+
{EFI_ENCODE_ERROR(EFI_WRITE_PROTECTED), EPERM},
44+
{EFI_ENCODE_ERROR(EFI_OUT_OF_RESOURCES), ENOMEM},
45+
{EFI_ENCODE_ERROR(EFI_VOLUME_CORRUPTED), EROFS},
46+
{EFI_ENCODE_ERROR(EFI_VOLUME_FULL), ENOSPC},
47+
{EFI_ENCODE_ERROR(EFI_NO_MEDIA), ENODEV},
48+
{EFI_ENCODE_ERROR(EFI_MEDIA_CHANGED), ENXIO},
49+
{EFI_ENCODE_ERROR(EFI_NOT_FOUND), ENOENT},
50+
{EFI_ENCODE_ERROR(EFI_ACCESS_DENIED), EACCES},
51+
{EFI_ENCODE_ERROR(EFI_NO_RESPONSE), EBUSY},
52+
{EFI_ENCODE_ERROR(EFI_NO_MAPPING), ENODEV},
53+
{EFI_ENCODE_ERROR(EFI_TIMEOUT), EBUSY},
54+
{EFI_ENCODE_ERROR(EFI_NOT_STARTED), EAGAIN},
55+
{EFI_ENCODE_ERROR(EFI_ALREADY_STARTED), EINVAL},
56+
{EFI_ENCODE_ERROR(EFI_ABORTED), EFAULT},
57+
{EFI_ENCODE_ERROR(EFI_ICMP_ERROR), EIO},
58+
{EFI_ENCODE_ERROR(EFI_TFTP_ERROR), EIO},
59+
{EFI_ENCODE_ERROR(EFI_PROTOCOL_ERROR), EINVAL},
60+
{EFI_ENCODE_ERROR(EFI_INCOMPATIBLE_VERSION), EINVAL},
61+
{EFI_ENCODE_ERROR(EFI_SECURITY_VIOLATION), EPERM},
62+
{EFI_ENCODE_ERROR(EFI_CRC_ERROR), EINVAL},
63+
{EFI_ENCODE_ERROR(EFI_END_OF_MEDIA), EPIPE},
64+
{EFI_ENCODE_ERROR(EFI_END_OF_FILE), EPIPE},
65+
{EFI_ENCODE_ERROR(EFI_INVALID_LANGUAGE), EINVAL},
66+
{EFI_ENCODE_ERROR(EFI_COMPROMISED_DATA), EINVAL},
67+
{EFI_ENCODE_ERROR(EFI_IP_ADDRESS_CONFLICT), EINVAL},
68+
{EFI_ENCODE_ERROR(EFI_HTTP_ERROR), EIO},
69+
{EFI_ENCODE_WARNING(EFI_WARN_UNKNOWN_GLYPH), EINVAL},
70+
{EFI_ENCODE_WARNING(EFI_WARN_DELETE_FAILURE), EROFS},
71+
{EFI_ENCODE_WARNING(EFI_WARN_WRITE_FAILURE), EROFS},
72+
{EFI_ENCODE_WARNING(EFI_WARN_BUFFER_TOO_SMALL), E2BIG},
73+
{EFI_ENCODE_WARNING(EFI_WARN_STALE_DATA), EINVAL},
74+
{EFI_ENCODE_WARNING(EFI_WARN_FILE_SYSTEM), EROFS},
75+
{EFI_ENCODE_WARNING(EFI_WARN_RESET_REQUIRED), EINTR},
76+
}};
77+
78+
LIBC_INLINE int uefi_status_to_errno(EFI_STATUS status) {
79+
for (auto it = UEFI_STATUS_ERRNO_MAP.begin();
80+
it != UEFI_STATUS_ERRNO_MAP.end(); it++) {
81+
const struct UefiStatusErrnoEntry entry = *it;
82+
if (entry.status == status)
83+
return entry.errno_value;
84+
}
85+
86+
// Unknown type
87+
return EINVAL;
88+
}
89+
90+
LIBC_INLINE EFI_STATUS errno_to_uefi_status(int errno_value) {
91+
for (auto it = UEFI_STATUS_ERRNO_MAP.begin();
92+
it != UEFI_STATUS_ERRNO_MAP.end(); it++) {
93+
const struct UefiStatusErrnoEntry entry = *it;
94+
if (entry.errno_value == errno_value)
95+
return entry.status;
96+
}
97+
98+
// Unknown type
99+
return EFI_INVALID_PARAMETER;
100+
}
101+
102+
} // namespace LIBC_NAMESPACE_DECL
103+
104+
#endif // LLVM_LIBC_SRC___SUPPORT_OSUTIL_UEFI_ERROR_H

libc/src/__support/OSUtil/uefi/exit.cpp

+4-2
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,16 @@
77
//===-----------------------------------------------------------------===//
88

99
#include "src/__support/OSUtil/exit.h"
10-
#include "include/Uefi.h"
10+
#include "config/uefi.h"
11+
#include "include/llvm-libc-types/EFI_SYSTEM_TABLE.h"
1112
#include "src/__support/macros/config.h"
1213

1314
namespace LIBC_NAMESPACE_DECL {
1415
namespace internal {
1516

1617
[[noreturn]] void exit(int status) {
17-
efi_system_table->BootServices->Exit(efi_image_handle, status, 0, nullptr);
18+
app.system_table->BootServices->Exit(__llvm_libc_efi_image_handle, status, 0,
19+
nullptr);
1820
__builtin_unreachable();
1921
}
2022

libc/src/__support/OSUtil/uefi/io.cpp

+10-5
Original file line numberDiff line numberDiff line change
@@ -8,28 +8,33 @@
88

99
#include "io.h"
1010

11+
#include "Uefi.h"
12+
#include "config/app.h"
1113
#include "src/__support/CPP/string_view.h"
1214
#include "src/__support/macros/config.h"
1315

1416
namespace LIBC_NAMESPACE_DECL {
1517

16-
ssize_t read_from_stdin(char *buf, size_t size) { return 0; }
18+
ssize_t read_from_stdin([[gnu::unused]] char *buf,
19+
[[gnu::unused]] size_t size) {
20+
return 0;
21+
}
1722

1823
void write_to_stdout(cpp::string_view msg) {
1924
// TODO: use mbstowcs once implemented
2025
for (size_t i = 0; i < msg.size(); i++) {
2126
char16_t e[2] = {msg[i], 0};
22-
efi_system_table->ConOut->OutputString(
23-
efi_system_table->ConOut, reinterpret_cast<const char16_t *>(&e));
27+
app.system_table->ConOut->OutputString(
28+
app.system_table->ConOut, reinterpret_cast<const char16_t *>(&e));
2429
}
2530
}
2631

2732
void write_to_stderr(cpp::string_view msg) {
2833
// TODO: use mbstowcs once implemented
2934
for (size_t i = 0; i < msg.size(); i++) {
3035
char16_t e[2] = {msg[i], 0};
31-
efi_system_table->StdErr->OutputString(
32-
efi_system_table->StdErr, reinterpret_cast<const char16_t *>(&e));
36+
app.system_table->StdErr->OutputString(
37+
app.system_table->StdErr, reinterpret_cast<const char16_t *>(&e));
3338
}
3439
}
3540

libc/startup/uefi/CMakeLists.txt

+50
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
# TODO: Use generic "add_startup_object" https://github.com/llvm/llvm-project/issues/133156
2+
function(add_startup_object name)
3+
cmake_parse_arguments(
4+
"ADD_STARTUP_OBJECT"
5+
"ALIAS" # Option argument
6+
"SRC" # Single value arguments
7+
"DEPENDS;COMPILE_OPTIONS" # Multi value arguments
8+
${ARGN}
9+
)
10+
11+
get_fq_target_name(${name} fq_target_name)
12+
if(ADD_STARTUP_OBJECT_ALIAS)
13+
get_fq_deps_list(fq_dep_list ${ADD_STARTUP_OBJECT_DEPENDS})
14+
add_library(${fq_target_name} ALIAS ${fq_dep_list})
15+
return()
16+
endif()
17+
18+
add_object_library(
19+
${name}
20+
SRCS ${ADD_STARTUP_OBJECT_SRC}
21+
COMPILE_OPTIONS ${ADD_STARTUP_OBJECT_COMPILE_OPTIONS}
22+
${ADD_STARTUP_OBJECT_UNPARSED_ARGUMENTS}
23+
DEPENDS ${ADD_STARTUP_OBJECT_DEPENDS}
24+
)
25+
set_target_properties(
26+
${fq_target_name}
27+
PROPERTIES
28+
OUTPUT_NAME ${name}.o
29+
)
30+
endfunction()
31+
32+
add_startup_object(
33+
crt1
34+
SRCS
35+
crt1.cpp
36+
DEPENDS
37+
libc.config.app_h
38+
libc.src.__support.OSUtil.uefi.uefi_util
39+
)
40+
41+
add_custom_target(libc-startup)
42+
set(startup_components crt1)
43+
foreach(target IN LISTS startup_components)
44+
set(fq_target_name libc.startup.uefi.${target})
45+
add_dependencies(libc-startup ${fq_target_name})
46+
install(FILES $<TARGET_OBJECTS:${fq_target_name}>
47+
DESTINATION ${LIBC_INSTALL_LIBRARY_DIR}
48+
RENAME $<TARGET_PROPERTY:${fq_target_name},OUTPUT_NAME>
49+
COMPONENT libc)
50+
endforeach()

libc/startup/uefi/crt1.cpp

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
//===-- Implementation of crt for UEFI ------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include "config/app.h"
10+
#include "include/llvm-libc-types/EFI_STATUS.h"
11+
#include "src/__support/OSUtil/uefi/error.h"
12+
#include "src/__support/macros/config.h"
13+
14+
namespace LIBC_NAMESPACE_DECL {
15+
AppProperties app;
16+
}
17+
18+
extern "C" {
19+
EFI_HANDLE __llvm_libc_efi_image_handle;
20+
EFI_SYSTEM_TABLE *__llvm_libc_efi_system_table;
21+
22+
int main(int argc, char **argv, char **envp);
23+
24+
EFI_STATUS EfiMain(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable) {
25+
LIBC_NAMESPACE::app.image_handle = ImageHandle;
26+
LIBC_NAMESPACE::app.system_table = SystemTable;
27+
28+
// TODO: we need the EFI_SHELL_PROTOCOL, malloc, free, and UTF16 -> UTF8
29+
// conversion.
30+
return LIBC_NAMESPACE::errno_to_uefi_status(main(0, nullptr, nullptr));
31+
}
32+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
add_custom_target(libc-startup-tests)
2+
add_dependencies(libc-integration-tests libc-startup-tests)
3+
4+
add_integration_test(
5+
startup_no_args_test
6+
SUITE libc-startup-tests
7+
SRCS
8+
main_without_args.cpp
9+
)

0 commit comments

Comments
 (0)