diff options
author | Liav A <liavalb@gmail.com> | 2020-02-09 16:28:56 +0200 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2020-02-09 19:38:17 +0100 |
commit | 7c507c27bf5b619c98b2e8cd023bca70b6ce8514 (patch) | |
tree | fb655d233079e1a1098df5fd952d533c7016efbc /Libraries/LibBareMetal/Output | |
parent | c45a5ff84025c2d4e7a305c7e2abb1c063ee95d4 (diff) | |
download | serenity-7c507c27bf5b619c98b2e8cd023bca70b6ce8514.zip |
LibBareMetal: Creating a new library for freestanding environments
Diffstat (limited to 'Libraries/LibBareMetal/Output')
-rw-r--r-- | Libraries/LibBareMetal/Output/Console.cpp | 97 | ||||
-rw-r--r-- | Libraries/LibBareMetal/Output/Console.h | 78 | ||||
-rw-r--r-- | Libraries/LibBareMetal/Output/kprintf.cpp | 167 | ||||
-rw-r--r-- | Libraries/LibBareMetal/Output/kstdio.h | 56 |
4 files changed, 398 insertions, 0 deletions
diff --git a/Libraries/LibBareMetal/Output/Console.cpp b/Libraries/LibBareMetal/Output/Console.cpp new file mode 100644 index 0000000000..fce5c15146 --- /dev/null +++ b/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() +{ +} diff --git a/Libraries/LibBareMetal/Output/Console.h b/Libraries/LibBareMetal/Output/Console.h new file mode 100644 index 0000000000..039a7958f0 --- /dev/null +++ b/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; +}; diff --git a/Libraries/LibBareMetal/Output/kprintf.cpp b/Libraries/LibBareMetal/Output/kprintf.cpp new file mode 100644 index 0000000000..e1a6f9ae3b --- /dev/null +++ b/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; +} diff --git a/Libraries/LibBareMetal/Output/kstdio.h b/Libraries/LibBareMetal/Output/kstdio.h new file mode 100644 index 0000000000..e5e0b2c1ae --- /dev/null +++ b/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 |