summaryrefslogtreecommitdiff
path: root/Libraries/LibBareMetal/Output
diff options
context:
space:
mode:
authorLiav A <liavalb@gmail.com>2020-02-09 16:28:56 +0200
committerAndreas Kling <kling@serenityos.org>2020-02-09 19:38:17 +0100
commit7c507c27bf5b619c98b2e8cd023bca70b6ce8514 (patch)
treefb655d233079e1a1098df5fd952d533c7016efbc /Libraries/LibBareMetal/Output
parentc45a5ff84025c2d4e7a305c7e2abb1c063ee95d4 (diff)
downloadserenity-7c507c27bf5b619c98b2e8cd023bca70b6ce8514.zip
LibBareMetal: Creating a new library for freestanding environments
Diffstat (limited to 'Libraries/LibBareMetal/Output')
-rw-r--r--Libraries/LibBareMetal/Output/Console.cpp97
-rw-r--r--Libraries/LibBareMetal/Output/Console.h78
-rw-r--r--Libraries/LibBareMetal/Output/kprintf.cpp167
-rw-r--r--Libraries/LibBareMetal/Output/kstdio.h56
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