Skip to content

Commit

Permalink
[libc] work on puts in uefi
Browse files Browse the repository at this point in the history
  • Loading branch information
RossComputerGuy committed Dec 20, 2024
1 parent 681b238 commit 2f7a61f
Show file tree
Hide file tree
Showing 15 changed files with 399 additions and 18 deletions.
13 changes: 13 additions & 0 deletions libc/config/uefi/entrypoints.txt
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,19 @@ set(TARGET_LIBC_ENTRYPOINTS
libc.src.stdbit.stdc_trailing_zeros_ull
libc.src.stdbit.stdc_trailing_zeros_us

# stdio.h entrypoints
libc.src.stdio.getchar
libc.src.stdio.printf
libc.src.stdio.putchar
libc.src.stdio.puts
libc.src.stdio.snprintf
libc.src.stdio.sprintf
libc.src.stdio.asprintf
libc.src.stdio.vprintf
libc.src.stdio.vsnprintf
libc.src.stdio.vsprintf
libc.src.stdio.vasprintf

# stdlib.h entrypoints
libc.src.stdlib._Exit
libc.src.stdlib.abort
Expand Down
1 change: 1 addition & 0 deletions libc/config/uefi/headers.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ set(TARGET_PUBLIC_HEADERS
libc.include.setjmp
libc.include.stdfix
libc.include.stdint
libc.include.stdio
libc.include.stdlib
libc.include.string
libc.include.strings
Expand Down
2 changes: 2 additions & 0 deletions libc/include/llvm-libc-types/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,9 @@ add_header(EFI_SIMPLE_TEXT_INPUT_PROTOCOL
HDR
EFI_SIMPLE_TEXT_INPUT_PROTOCOL.h
DEPENDS
libc.include.llvm-libc-macros.EFIAPI_macros
libc.include.llvm-libc-macros.stdint_macros
.EFI_EVENT
.EFI_STATUS
.char16_t
)
Expand Down
2 changes: 2 additions & 0 deletions libc/include/llvm-libc-types/EFI_SIMPLE_TEXT_INPUT_PROTOCOL.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@
#ifndef LLVM_LIBC_TYPES_EFI_SIMPLE_TEXT_INPUT_PROTOCOL_H
#define LLVM_LIBC_TYPES_EFI_SIMPLE_TEXT_INPUT_PROTOCOL_H

#include "../llvm-libc-macros/EFIAPI-macros.h"
#include "../llvm-libc-macros/stdint-macros.h"
#include "EFI_EVENT.h"
#include "EFI_STATUS.h"
#include "char16_t.h"

Expand Down
4 changes: 4 additions & 0 deletions libc/src/__support/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -359,6 +359,10 @@ add_subdirectory(StringUtil)
add_subdirectory(GPU)
add_subdirectory(RPC)

if(LIBC_TARGET_OS_IS_UEFI)
add_subdirectory(UEFI)
endif()

# Thread support is used by other "File". So, we add the "threads"
# before "File".
add_subdirectory(threads)
Expand Down
11 changes: 11 additions & 0 deletions libc/src/__support/UEFI/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
add_object_library(
file
SRCS
file.cpp
HDRS
file.h
DEPENDS
libc.include.uefi
libc.hdr.types.FILE
libc.src.__support.CPP.new
)
67 changes: 67 additions & 0 deletions libc/src/__support/UEFI/file.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
#include "file.h"
#include "hdr/types/FILE.h"
#include "src/__support/macros/config.h"
#include <Uefi.h>

#define STDIN_FILENO 0
#define STDOUT_FILENO 1
#define STDERR_FILENO 2

namespace LIBC_NAMESPACE_DECL {
bool File::needsReset() { return handle_type == FileHandleId; }

void File::reset() {
if (handle_type != FileHandleId)
return;

if (handle.id == STDIN_FILENO) {
handle = (FileHandle){
.simple_text_input = efi_system_table->ConIn,
};
handle_type = FileHandleSimpleTextInput;
} else {
handle = (FileHandle){
.simple_text_output = handle.id == STDERR_FILENO
? efi_system_table->StdErr
: efi_system_table->ConOut,
};
handle_type = FileHandleSimpleTextOutput;
}
}

size_t File::write(const void *data, size_t data_len) {
if (needsReset())
reset();

if (handle_type == FileHandleSimpleTextOutput) {
handle.simple_text_output->OutputString(
handle.simple_text_output, reinterpret_cast<const char16_t *>(data));
return data_len;
}
return 0;
}

File stdin(
(FileHandle){
.id = STDIN_FILENO,
},
FileHandleId);

File stdout(
(FileHandle){
.id = STDOUT_FILENO,
},
FileHandleId);

File stderr(
(FileHandle){
.id = STDERR_FILENO,
},
FileHandleId);
} // namespace LIBC_NAMESPACE_DECL

extern "C" {
FILE *stdin = reinterpret_cast<FILE *>(&LIBC_NAMESPACE::stdin);
FILE *stdout = reinterpret_cast<FILE *>(&LIBC_NAMESPACE::stdout);
FILE *stderr = reinterpret_cast<FILE *>(&LIBC_NAMESPACE::stderr);
}
46 changes: 46 additions & 0 deletions libc/src/__support/UEFI/file.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#ifndef LLVM_LIBC_SRC___SUPPORT_UEFI_FILE_H
#define LLVM_LIBC_SRC___SUPPORT_UEFI_FILE_H

#include "include/llvm-libc-types/EFI_SIMPLE_TEXT_INPUT_PROTOCOL.h"
#include "include/llvm-libc-types/EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.h"
#include "src/__support/CPP/new.h"
#include "src/__support/macros/config.h"

namespace LIBC_NAMESPACE_DECL {

enum FileHandleType {
FileHandleId,
FileHandleSimpleTextInput,
FileHandleSimpleTextOutput,
};

union FileHandle {
int id;
EFI_SIMPLE_TEXT_INPUT_PROTOCOL *simple_text_input;
EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *simple_text_output;
};

class File {
FileHandle handle;
FileHandleType handle_type;

private:
bool needsReset();

public:
constexpr File(FileHandle handle, FileHandleType handle_type)
: handle(handle), handle_type(handle_type) {}

void reset();

size_t read(void *data, size_t len);
size_t write(const void *data, size_t len);
};

extern File stdin;
extern File stdout;
extern File stderr;

} // namespace LIBC_NAMESPACE_DECL

#endif // LLVM_LIBC_SRC___SUPPORT_UEFI_FILE_H
38 changes: 20 additions & 18 deletions libc/src/stdio/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -240,26 +240,28 @@ add_entrypoint_object(
add_subdirectory(printf_core)
add_subdirectory(scanf_core)

add_entrypoint_object(
remove
ALIAS
DEPENDS
.${LIBC_TARGET_OS}.remove
)
if(NOT LIBC_TARGET_OS_IS_UEFI)
add_entrypoint_object(
remove
ALIAS
DEPENDS
.${LIBC_TARGET_OS}.remove
)

add_entrypoint_object(
rename
ALIAS
DEPENDS
.${LIBC_TARGET_OS}.rename
)
add_entrypoint_object(
rename
ALIAS
DEPENDS
.${LIBC_TARGET_OS}.rename
)

add_entrypoint_object(
fdopen
ALIAS
DEPENDS
.${LIBC_TARGET_OS}.fdopen
)
add_entrypoint_object(
fdopen
ALIAS
DEPENDS
.${LIBC_TARGET_OS}.fdopen
)
endif()

# These entrypoints have multiple potential implementations.
add_stdio_entrypoint_object(feof)
Expand Down
59 changes: 59 additions & 0 deletions libc/src/stdio/uefi/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
add_entrypoint_object(
getchar
SRCS
getchar.cpp
HDRS
../getchar.h
DEPENDS
libc.hdr.stdio_macros
libc.src.__support.UEFI.file
)

add_entrypoint_object(
printf
SRCS
printf.cpp
HDRS
../printf.h
DEPENDS
libc.src.stdio.printf_core.printf_main
libc.src.stdio.printf_core.writer
libc.src.__support.arg_list
libc.src.__support.OSUtil.osutil
)

add_entrypoint_object(
putchar
SRCS
putchar.cpp
HDRS
../putchar.h
DEPENDS
libc.src.__support.OSUtil.osutil
libc.src.__support.CPP.string_view
libc.src.__support.UEFI.file
)

add_entrypoint_object(
puts
SRCS
puts.cpp
HDRS
../puts.h
DEPENDS
libc.src.__support.UEFI.file
libc.src.string.strlen
)

add_entrypoint_object(
vprintf
SRCS
vprintf.cpp
HDRS
../vprintf.h
DEPENDS
libc.src.stdio.printf_core.printf_main
libc.src.stdio.printf_core.writer
libc.src.__support.arg_list
libc.src.__support.OSUtil.osutil
)
26 changes: 26 additions & 0 deletions libc/src/stdio/uefi/getchar.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
//===-- Implementation of getchar -----------------------------------------===//
//
// 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 "src/stdio/getchar.h"
#include "src/__support/UEFI/file.h"

#include "hdr/stdio_macros.h" // for EOF.
#include "hdr/types/FILE.h"
#include "src/__support/macros/config.h"
#include "src/errno/libc_errno.h"

namespace LIBC_NAMESPACE_DECL {

LLVM_LIBC_FUNCTION(int, getchar, ()) {
unsigned char c;
if (stdin.read(&c, 1) != 1)
return EOF;
return c;
}

} // namespace LIBC_NAMESPACE_DECL
53 changes: 53 additions & 0 deletions libc/src/stdio/uefi/printf.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
//===-- Implementation of printf for baremetal ------------------*- 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
//
//===----------------------------------------------------------------------===//

#include "src/stdio/printf.h"
#include "src/__support/OSUtil/io.h"
#include "src/__support/arg_list.h"
#include "src/__support/macros/config.h"
#include "src/stdio/printf_core/core_structs.h"
#include "src/stdio/printf_core/printf_main.h"
#include "src/stdio/printf_core/writer.h"

#include <stdarg.h>
#include <stddef.h>

namespace LIBC_NAMESPACE_DECL {

namespace {

LIBC_INLINE int raw_write_hook(cpp::string_view new_str, void *) {
write_to_stderr(new_str);
return printf_core::WRITE_OK;
}

} // namespace

LLVM_LIBC_FUNCTION(int, printf, (const char *__restrict format, ...)) {
va_list vlist;
va_start(vlist, format);
internal::ArgList args(vlist); // This holder class allows for easier copying
// and pointer semantics, as well as handling
// destruction automatically.
va_end(vlist);
constexpr size_t BUFF_SIZE = 1024;
char buffer[BUFF_SIZE];

printf_core::WriteBuffer wb(buffer, BUFF_SIZE, &raw_write_hook, nullptr);
printf_core::Writer writer(&wb);

int retval = printf_core::printf_main(&writer, format, args);

int flushval = wb.overflow_write("");
if (flushval != printf_core::WRITE_OK)
retval = flushval;

return retval;
}

} // namespace LIBC_NAMESPACE_DECL
24 changes: 24 additions & 0 deletions libc/src/stdio/uefi/putchar.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
//===-- Baremetal Implementation of putchar -------------------------------===//
//
// 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 "src/stdio/putchar.h"
#include "src/__support/CPP/string_view.h"
#include "src/__support/OSUtil/io.h"
#include "src/__support/macros/config.h"

namespace LIBC_NAMESPACE_DECL {

LLVM_LIBC_FUNCTION(int, putchar, (int c)) {
char uc = static_cast<char>(c);

write_to_stderr(cpp::string_view(&uc, 1));

return 0;
}

} // namespace LIBC_NAMESPACE_DECL
Loading

0 comments on commit 2f7a61f

Please sign in to comment.