126 lines
3.4 KiB
C++
126 lines
3.4 KiB
C++
/*
|
|
* Generic Console
|
|
*
|
|
* Copyright (C) 2009-2011 Udo Steinberg <udo@hypervisor.org>
|
|
* Economic rights: Technische Universitaet Dresden (Germany)
|
|
*
|
|
* Copyright (C) 2012-2013 Udo Steinberg, Intel Corporation.
|
|
* Copyright (C) 2019-2025 Udo Steinberg, BlueRock Security, Inc.
|
|
*
|
|
* This file is part of the NOVA microhypervisor.
|
|
*
|
|
* NOVA is free software: you can redistribute it and/or modify it
|
|
* under the terms of the GNU General Public License version 2 as
|
|
* published by the Free Software Foundation.
|
|
*
|
|
* NOVA is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License version 2 for more details.
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include <stdarg.h>
|
|
#include "acpi_gas.hpp"
|
|
#include "debug.hpp"
|
|
#include "initprio.hpp"
|
|
#include "list.hpp"
|
|
#include "spinlock.hpp"
|
|
|
|
class Console : public List<Console>
|
|
{
|
|
private:
|
|
enum class Mode
|
|
{
|
|
FLAGS = 0,
|
|
WIDTH = 1,
|
|
PRECS = 2,
|
|
};
|
|
|
|
enum Flags
|
|
{
|
|
SIGNED = BIT (0),
|
|
ALT_FORM = BIT (1),
|
|
ZERO_PAD = BIT (2),
|
|
};
|
|
|
|
static inline constinit Console *dormant { nullptr };
|
|
static inline constinit Console *enabled { nullptr };
|
|
static inline constinit Spinlock lock;
|
|
|
|
[[nodiscard]] virtual bool outc (char) const = 0;
|
|
|
|
static void putc (char c)
|
|
{
|
|
for (Console *e { enabled }, *n; e; e = n) {
|
|
|
|
n = e->next;
|
|
|
|
if (!e->outc (c)) [[unlikely]]
|
|
e->disable();
|
|
}
|
|
}
|
|
|
|
static void print_num (uint64_t, unsigned, unsigned, unsigned);
|
|
static void print_str (char const *, unsigned, unsigned);
|
|
|
|
FORMAT (1,0)
|
|
static void vprintf (char const *, va_list);
|
|
|
|
protected:
|
|
Console() : List { dormant } {}
|
|
|
|
[[nodiscard]] virtual bool init() const { return true; }
|
|
[[nodiscard]] virtual bool fini() const { return true; }
|
|
|
|
[[nodiscard]] virtual bool match_dbgp (Debug::Type, Debug::Subtype) const { return false; }
|
|
[[nodiscard]] virtual bool using_regs (Acpi_gas const &) const { return false; }
|
|
[[nodiscard]] virtual bool setup_regs (Acpi_gas const &) { return false; }
|
|
|
|
void enable()
|
|
{
|
|
remove (dormant);
|
|
insert (enabled);
|
|
}
|
|
|
|
void disable()
|
|
{
|
|
remove (enabled);
|
|
insert (dormant);
|
|
}
|
|
|
|
public:
|
|
FORMAT (1,2)
|
|
static void print (char const *, ...);
|
|
|
|
static void flush()
|
|
{
|
|
for (Console *e { enabled }, *n; e; e = n) {
|
|
|
|
n = e->next;
|
|
|
|
if (!e->fini()) [[unlikely]]
|
|
e->disable();
|
|
}
|
|
}
|
|
|
|
static void bind (Debug::Type t, Debug::Subtype s, Acpi_gas const &r)
|
|
{
|
|
if (!r.addr || r.bits < 8) [[unlikely]]
|
|
return;
|
|
|
|
for (auto e { enabled }; e; e = e->next)
|
|
if (e->using_regs (r))
|
|
return;
|
|
|
|
for (auto d { dormant }; d; d = d->next)
|
|
if (d->using_regs (r))
|
|
return;
|
|
|
|
for (auto d { dormant }; d; d = d->next)
|
|
if (d->match_dbgp (t, s) && d->setup_regs (r))
|
|
return;
|
|
}
|
|
};
|