mirror of
https://github.com/RGBCube/serenity
synced 2025-07-26 02:07:35 +00:00
LibBareMetal: Creating a new library for freestanding environments
This commit is contained in:
parent
c45a5ff840
commit
7c507c27bf
8 changed files with 854 additions and 0 deletions
103
Libraries/LibBareMetal/IO.h
Normal file
103
Libraries/LibBareMetal/IO.h
Normal file
|
@ -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
Libraries/LibBareMetal/Makefile
Normal file
1
Libraries/LibBareMetal/Makefile
Normal file
|
@ -0,0 +1 @@
|
||||||
|
include ../../Makefile.common
|
97
Libraries/LibBareMetal/Output/Console.cpp
Normal file
97
Libraries/LibBareMetal/Output/Console.cpp
Normal file
|
@ -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
Libraries/LibBareMetal/Output/Console.h
Normal file
78
Libraries/LibBareMetal/Output/Console.h
Normal file
|
@ -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
Libraries/LibBareMetal/Output/kprintf.cpp
Normal file
167
Libraries/LibBareMetal/Output/kprintf.cpp
Normal file
|
@ -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
Libraries/LibBareMetal/Output/kstdio.h
Normal file
56
Libraries/LibBareMetal/Output/kstdio.h
Normal file
|
@ -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
Libraries/LibBareMetal/StdLib.cpp
Normal file
265
Libraries/LibBareMetal/StdLib.cpp
Normal file
|
@ -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
Libraries/LibBareMetal/StdLib.h
Normal file
87
Libraries/LibBareMetal/StdLib.h
Normal file
|
@ -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
|
Loading…
Add table
Add a link
Reference in a new issue