Переглянути джерело

LibBareMetal: Creating a new library for freestanding environments

Liav A 5 роки тому
батько
коміт
7c507c27bf

+ 103 - 0
Libraries/LibBareMetal/IO.h

@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ *    list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include <AK/Types.h>
+
+#if defined(KERNEL)
+#    include <Kernel/Arch/i386/CPU.h>
+#    include <Kernel/Devices/VMWareBackdoor.h>
+#endif
+
+namespace IO {
+
+inline u8 in8(u16 port)
+{
+    u8 value;
+    asm volatile("inb %1, %0"
+                 : "=a"(value)
+                 : "Nd"(port));
+    return value;
+}
+
+inline u16 in16(u16 port)
+{
+    u16 value;
+    asm volatile("inw %1, %0"
+                 : "=a"(value)
+                 : "Nd"(port));
+    return value;
+}
+
+inline u32 in32(u16 port)
+{
+    u32 value;
+    asm volatile("inl %1, %0"
+                 : "=a"(value)
+                 : "Nd"(port));
+    return value;
+}
+
+inline void repeated_in16(u16 port, u8* buffer, int buffer_size)
+{
+    asm volatile("rep insw"
+                 : "+D"(buffer), "+c"(buffer_size)
+                 : "d"(port)
+                 : "memory");
+}
+
+inline void out8(u16 port, u8 value)
+{
+    asm volatile("outb %0, %1" ::"a"(value), "Nd"(port));
+}
+
+inline void out16(u16 port, u16 value)
+{
+    asm volatile("outw %0, %1" ::"a"(value), "Nd"(port));
+}
+
+inline void out32(u16 port, u32 value)
+{
+    asm volatile("outl %0, %1" ::"a"(value), "Nd"(port));
+}
+
+inline void repeated_out16(u16 port, const u8* data, int data_size)
+{
+    asm volatile("rep outsw"
+                 : "+S"(data), "+c"(data_size)
+                 : "d"(port));
+}
+
+inline void delay()
+{
+    // ~3 microsecs
+    for (auto i = 0; i < 32; i++) {
+        IO::in8(0x80);
+    }
+}
+
+}

+ 1 - 0
Libraries/LibBareMetal/Makefile

@@ -0,0 +1 @@
+include ../../Makefile.common

+ 97 - 0
Libraries/LibBareMetal/Output/Console.cpp

@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ *    list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <LibBareMetal/IO.h>
+#include <LibBareMetal/Output/Console.h>
+#include <LibBareMetal/Output/kstdio.h>
+
+// Bytes output to 0xE9 end up on the Bochs console. It's very handy.
+#define CONSOLE_OUT_TO_E9
+
+static Console* s_the;
+
+Console& Console::the()
+{
+    ASSERT(s_the);
+    return *s_the;
+}
+
+bool Console::is_initialized()
+{
+    return s_the != nullptr;
+}
+
+Console::Console()
+#if defined(KERNEL)
+    : CharacterDevice(5, 1)
+#endif
+{
+    s_the = this;
+}
+
+Console::~Console()
+{
+}
+
+#if defined(KERNEL)
+bool Console::can_read(const FileDescription&) const
+{
+    return false;
+}
+
+ssize_t Console::read(FileDescription&, u8*, ssize_t)
+{
+    // FIXME: Implement reading from the console.
+    //        Maybe we could use a ring buffer for this device?
+    return 0;
+}
+
+ssize_t Console::write(FileDescription&, const u8* data, ssize_t size)
+{
+    if (!size)
+        return 0;
+    if (!m_implementation)
+        return 0;
+    for (ssize_t i = 0; i < size; ++i)
+        put_char(data[i]);
+    return size;
+}
+#endif
+
+void Console::put_char(char ch)
+{
+#ifdef CONSOLE_OUT_TO_E9
+    //if (ch != 27)
+    IO::out8(0xe9, ch);
+#endif
+    m_logbuffer.enqueue(ch);
+    if (m_implementation)
+        m_implementation->on_sysconsole_receive(ch);
+}
+
+ConsoleImplementation::~ConsoleImplementation()
+{
+}

+ 78 - 0
Libraries/LibBareMetal/Output/Console.h

@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ *    list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include <AK/CircularQueue.h>
+#include <AK/Vector.h>
+#if defined(KERNEL)
+#    include <Kernel/Devices/CharacterDevice.h>
+#endif
+
+class ConsoleImplementation {
+public:
+    virtual ~ConsoleImplementation();
+    virtual void on_sysconsole_receive(u8) = 0;
+};
+
+#if defined(KERNEL)
+class Console final : public CharacterDevice {
+    AK_MAKE_ETERNAL
+#elif defined(BOOTSTRAPPER)
+class Console {
+#endif
+public:
+    static Console& the();
+    static bool is_initialized();
+
+    Console();
+#if defined(KERNEL)
+    virtual ~Console() override;
+#elif defined(BOOTSTRAPPER)
+    virtual ~Console();
+#endif
+
+#if defined(KERNEL)
+    // ^CharacterDevice
+    virtual bool can_read(const FileDescription&) const override;
+    virtual bool can_write(const FileDescription&) const override { return true; }
+    virtual ssize_t read(FileDescription&, u8*, ssize_t) override;
+    virtual ssize_t write(FileDescription&, const u8*, ssize_t) override;
+    virtual const char* class_name() const override { return "Console"; }
+#endif
+    void set_implementation(ConsoleImplementation* implementation)
+    {
+        m_implementation = implementation;
+    }
+
+    void put_char(char);
+
+    const CircularQueue<char, 16384>& logbuffer() const { return m_logbuffer; }
+
+private:
+    ConsoleImplementation* m_implementation { nullptr };
+    CircularQueue<char, 16384> m_logbuffer;
+};

+ 167 - 0
Libraries/LibBareMetal/Output/kprintf.cpp

@@ -0,0 +1,167 @@
+/*
+ * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ *    list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <AK/PrintfImplementation.h>
+#include <AK/Types.h>
+#include <LibBareMetal/IO.h>
+#include <LibBareMetal/Output/Console.h>
+#include <LibBareMetal/Output/kstdio.h>
+
+#include <LibC/stdarg.h>
+
+#if defined(KERNEL)
+#    include <Kernel/Process.h>
+#endif
+
+static bool serial_debug;
+
+void set_serial_debug(bool on_or_off)
+{
+    serial_debug = on_or_off;
+}
+
+int get_serial_debug()
+{
+    return serial_debug;
+}
+
+static void color_on()
+{
+    IO::out8(0xe9, 0x1b);
+    IO::out8(0xe9, '[');
+    IO::out8(0xe9, '3');
+    IO::out8(0xe9, '6');
+    IO::out8(0xe9, 'm');
+}
+
+static void color_off()
+{
+    IO::out8(0xe9, 0x1b);
+    IO::out8(0xe9, '[');
+    IO::out8(0xe9, '0');
+    IO::out8(0xe9, 'm');
+}
+
+static void serial_putch(char ch)
+{
+    static bool serial_ready = false;
+    static bool was_cr = false;
+
+    if (!serial_ready) {
+        IO::out8(0x3F8 + 1, 0x00);
+        IO::out8(0x3F8 + 3, 0x80);
+        IO::out8(0x3F8 + 0, 0x02);
+        IO::out8(0x3F8 + 1, 0x00);
+        IO::out8(0x3F8 + 3, 0x03);
+        IO::out8(0x3F8 + 2, 0xC7);
+        IO::out8(0x3F8 + 4, 0x0B);
+
+        serial_ready = true;
+    }
+
+    while ((IO::in8(0x3F8 + 5) & 0x20) == 0)
+        ;
+
+    if (ch == '\n' && !was_cr)
+        IO::out8(0x3F8, '\r');
+
+    IO::out8(0x3F8, ch);
+
+    if (ch == '\r')
+        was_cr = true;
+    else
+        was_cr = false;
+}
+
+static void console_putch(char*&, char ch)
+{
+    if (serial_debug)
+        serial_putch(ch);
+
+    // It would be bad to reach the assert in Console()::the() and do a stack overflow
+
+    if (Console::is_initialized()) {
+        Console::the().put_char(ch);
+    } else {
+        IO::out8(0xe9, ch);
+    }
+}
+
+int kprintf(const char* fmt, ...)
+{
+    color_on();
+    va_list ap;
+    va_start(ap, fmt);
+    int ret = printf_internal(console_putch, nullptr, fmt, ap);
+    va_end(ap);
+    color_off();
+    return ret;
+}
+
+static void buffer_putch(char*& bufptr, char ch)
+{
+    *bufptr++ = ch;
+}
+
+int sprintf(char* buffer, const char* fmt, ...)
+{
+    va_list ap;
+    va_start(ap, fmt);
+    int ret = printf_internal(buffer_putch, buffer, fmt, ap);
+    buffer[ret] = '\0';
+    va_end(ap);
+    return ret;
+}
+
+static void debugger_out(char ch)
+{
+    if (serial_debug)
+        serial_putch(ch);
+    IO::out8(0xe9, ch);
+}
+
+static void debugger_putch(char*&, char ch)
+{
+    debugger_out(ch);
+}
+
+extern "C" int dbgputstr(const char* characters, int length)
+{
+    for (int i = 0; i < length; ++i)
+        debugger_out(characters[i]);
+    return 0;
+}
+
+extern "C" int dbgprintf(const char* fmt, ...)
+{
+    color_on();
+    va_list ap;
+    va_start(ap, fmt);
+    int ret = printf_internal(debugger_putch, nullptr, fmt, ap);
+    va_end(ap);
+    color_off();
+    return ret;
+}

+ 56 - 0
Libraries/LibBareMetal/Output/kstdio.h

@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ *    list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include <AK/Types.h>
+
+extern "C" {
+int dbgprintf(const char* fmt, ...);
+int dbgputstr(const char*, int);
+int kprintf(const char* fmt, ...);
+int sprintf(char* buf, const char* fmt, ...);
+void set_serial_debug(bool on_or_off);
+int get_serial_debug();
+}
+
+#if defined(KERNEL) || defined(BOOTSTRAPPER)
+#    define printf dbgprintf
+#endif
+
+#ifndef __serenity__
+#    define dbgprintf printf
+#endif
+
+#ifdef __cplusplus
+
+template<size_t N>
+inline int dbgputstr(const char (&array)[N])
+{
+    return ::dbgputstr(array, N);
+}
+
+#endif

+ 265 - 0
Libraries/LibBareMetal/StdLib.cpp

@@ -0,0 +1,265 @@
+/*
+ * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ *    list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <AK/Assertions.h>
+#include <AK/String.h>
+#include <AK/Types.h>
+#include <LibBareMetal/StdLib.h>
+
+#ifdef KERNEL
+#    include <Kernel/Arch/i386/CPU.h>
+#    include <Kernel/Heap/kmalloc.h>
+#    include <Kernel/VM/MemoryManager.h>
+#endif
+
+#ifdef KERNEL
+String copy_string_from_user(const char* user_str, size_t user_str_size)
+{
+    SmapDisabler disabler;
+    size_t length = strnlen(user_str, user_str_size);
+    return String(user_str, length);
+}
+#endif
+
+extern "C" {
+
+#ifdef KERNEL
+void copy_to_user(void* dest_ptr, const void* src_ptr, size_t n)
+{
+    ASSERT(is_user_range(VirtualAddress(dest_ptr), n));
+    SmapDisabler disabler;
+    memcpy(dest_ptr, src_ptr, n);
+}
+
+void copy_from_user(void* dest_ptr, const void* src_ptr, size_t n)
+{
+    ASSERT(is_user_range(VirtualAddress(src_ptr), n));
+    SmapDisabler disabler;
+    memcpy(dest_ptr, src_ptr, n);
+}
+#endif
+
+void* memcpy(void* dest_ptr, const void* src_ptr, size_t n)
+{
+    size_t dest = (size_t)dest_ptr;
+    size_t src = (size_t)src_ptr;
+    // FIXME: Support starting at an unaligned address.
+    if (!(dest & 0x3) && !(src & 0x3) && n >= 12) {
+        size_t size_ts = n / sizeof(size_t);
+        asm volatile(
+            "rep movsl\n"
+            : "=S"(src), "=D"(dest)
+            : "S"(src), "D"(dest), "c"(size_ts)
+            : "memory");
+        n -= size_ts * sizeof(size_t);
+        if (n == 0)
+            return dest_ptr;
+    }
+    asm volatile(
+        "rep movsb\n" ::"S"(src), "D"(dest), "c"(n)
+        : "memory");
+    return dest_ptr;
+}
+
+void* memmove(void* dest, const void* src, size_t n)
+{
+    if (dest < src)
+        return memcpy(dest, src, n);
+
+    u8* pd = (u8*)dest;
+    const u8* ps = (const u8*)src;
+    for (pd += n, ps += n; n--;)
+        *--pd = *--ps;
+    return dest;
+}
+
+char* strcpy(char* dest, const char* src)
+{
+    auto* dest_ptr = dest;
+    auto* src_ptr = src;
+    while ((*dest_ptr++ = *src_ptr++) != '\0')
+        ;
+    return dest;
+}
+
+char* strncpy(char* dest, const char* src, size_t n)
+{
+    size_t i;
+    for (i = 0; i < n && src[i] != '\0'; ++i)
+        dest[i] = src[i];
+    for (; i < n; ++i)
+        dest[i] = '\0';
+    return dest;
+}
+
+#ifdef KERNEL
+void memset_user(void* dest_ptr, int c, size_t n)
+{
+    ASSERT(is_user_range(VirtualAddress(dest_ptr), n));
+    SmapDisabler disabler;
+    memset(dest_ptr, c, n);
+}
+#endif
+
+void* memset(void* dest_ptr, int c, size_t n)
+{
+    size_t dest = (size_t)dest_ptr;
+    // FIXME: Support starting at an unaligned address.
+    if (!(dest & 0x3) && n >= 12) {
+        size_t size_ts = n / sizeof(size_t);
+        size_t expanded_c = (u8)c;
+        expanded_c |= expanded_c << 8;
+        expanded_c |= expanded_c << 16;
+        asm volatile(
+            "rep stosl\n"
+            : "=D"(dest)
+            : "D"(dest), "c"(size_ts), "a"(expanded_c)
+            : "memory");
+        n -= size_ts * sizeof(size_t);
+        if (n == 0)
+            return dest_ptr;
+    }
+    asm volatile(
+        "rep stosb\n"
+        : "=D"(dest), "=c"(n)
+        : "0"(dest), "1"(n), "a"(c)
+        : "memory");
+    return dest_ptr;
+}
+
+char* strrchr(const char* str, int ch)
+{
+    char* last = nullptr;
+    char c;
+    for (; (c = *str); ++str) {
+        if (c == ch)
+            last = const_cast<char*>(str);
+    }
+    return last;
+}
+
+size_t strlen(const char* str)
+{
+    size_t len = 0;
+    while (*(str++))
+        ++len;
+    return len;
+}
+
+size_t strnlen(const char* str, size_t maxlen)
+{
+    size_t len = 0;
+    for (; len < maxlen && *str; str++)
+        len++;
+    return len;
+}
+
+int strcmp(const char* s1, const char* s2)
+{
+    for (; *s1 == *s2; ++s1, ++s2) {
+        if (*s1 == 0)
+            return 0;
+    }
+    return *(const u8*)s1 < *(const u8*)s2 ? -1 : 1;
+}
+
+char* strdup(const char* str)
+{
+    size_t len = strlen(str);
+    char* new_str = (char*)kmalloc(len + 1);
+    strcpy(new_str, str);
+    return new_str;
+}
+
+int memcmp(const void* v1, const void* v2, size_t n)
+{
+    auto* s1 = (const u8*)v1;
+    auto* s2 = (const u8*)v2;
+    while (n-- > 0) {
+        if (*s1++ != *s2++)
+            return s1[-1] < s2[-1] ? -1 : 1;
+    }
+    return 0;
+}
+
+int strncmp(const char* s1, const char* s2, size_t n)
+{
+    if (!n)
+        return 0;
+    do {
+        if (*s1 != *s2++)
+            return *(const unsigned char*)s1 - *(const unsigned char*)--s2;
+        if (*s1++ == 0)
+            break;
+    } while (--n);
+    return 0;
+}
+
+char* strstr(const char* haystack, const char* needle)
+{
+    char nch;
+    char hch;
+
+    if ((nch = *needle++) != 0) {
+        size_t len = strlen(needle);
+        do {
+            do {
+                if ((hch = *haystack++) == 0)
+                    return nullptr;
+            } while (hch != nch);
+        } while (strncmp(haystack, needle, len) != 0);
+        --haystack;
+    }
+    return const_cast<char*>(haystack);
+}
+
+[[noreturn]] void __cxa_pure_virtual()
+{
+    ASSERT_NOT_REACHED();
+}
+
+#ifdef KERNEL
+void* realloc(void* p, size_t s)
+{
+    return krealloc(p, s);
+}
+#endif
+
+void free(void* p)
+{
+    return kfree(p);
+}
+
+[[noreturn]] void __stack_chk_fail()
+{
+    ASSERT_NOT_REACHED();
+}
+
+[[noreturn]] void __stack_chk_fail_local()
+{
+    ASSERT_NOT_REACHED();
+}
+}

+ 87 - 0
Libraries/LibBareMetal/StdLib.h

@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ *    list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include <AK/Types.h>
+
+#if defined(KERNEL)
+
+namespace AK {
+class String;
+}
+
+namespace Syscall {
+struct StringArgument;
+}
+
+AK::String copy_string_from_user(const char*, size_t);
+
+#endif
+
+extern "C" {
+
+static_assert(sizeof(size_t) == 4);
+
+#if defined(KERNEL)
+void copy_to_user(void*, const void*, size_t);
+void copy_from_user(void*, const void*, size_t);
+void memset_user(void*, int, size_t);
+#endif
+
+void* memcpy(void*, const void*, size_t);
+char* strcpy(char*, const char*);
+char* strncpy(char*, const char*, size_t);
+int strncmp(const char* s1, const char* s2, size_t n);
+char* strstr(const char* haystack, const char* needle);
+int strcmp(char const*, const char*);
+size_t strlen(const char*);
+size_t strnlen(const char*, size_t);
+void* memset(void*, int, size_t);
+char* strdup(const char*);
+int memcmp(const void*, const void*, size_t);
+char* strrchr(const char* str, int ch);
+void* memmove(void* dest, const void* src, size_t n);
+
+inline u16 ntohs(u16 w) { return (w & 0xff) << 8 | ((w >> 8) & 0xff); }
+inline u16 htons(u16 w) { return (w & 0xff) << 8 | ((w >> 8) & 0xff); }
+}
+
+#if defined(KERNEL)
+
+template<typename T>
+inline void copy_from_user(T* dest, const T* src)
+{
+    copy_from_user(dest, src, sizeof(T));
+}
+
+template<typename T>
+inline void copy_to_user(T* dest, const T* src)
+{
+    copy_to_user(dest, src, sizeof(T));
+}
+
+#endif