[libc][uefi] add crt1 (#132150)
Adds `crt1.o` for the UEFI platform in the LLVM C library. This makes things start to become useful.
This commit is contained in:
@@ -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
|
||||
|
||||
34
libc/config/uefi/app.h
Normal file
34
libc/config/uefi/app.h
Normal file
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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: []
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
)
|
||||
|
||||
104
libc/src/__support/OSUtil/uefi/error.h
Normal file
104
libc/src/__support/OSUtil/uefi/error.h
Normal file
@@ -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
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
50
libc/startup/uefi/CMakeLists.txt
Normal file
50
libc/startup/uefi/CMakeLists.txt
Normal file
@@ -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()
|
||||
32
libc/startup/uefi/crt1.cpp
Normal file
32
libc/startup/uefi/crt1.cpp
Normal file
@@ -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));
|
||||
}
|
||||
}
|
||||
9
libc/test/integration/startup/uefi/CMakeLists.txt
Normal file
9
libc/test/integration/startup/uefi/CMakeLists.txt
Normal file
@@ -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
|
||||
)
|
||||
@@ -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; }
|
||||
Reference in New Issue
Block a user