summaryrefslogtreecommitdiff
path: root/Kernel/Graphics/Console/BootFramebufferConsole.cpp
blob: c950072a7cbba4d12357e8732b22886df4202a99 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
/*
 * Copyright (c) 2022, the SerenityOS developers.
 *
 * SPDX-License-Identifier: BSD-2-Clause
 */

#include <Kernel/Graphics/Console/BootFramebufferConsole.h>
#include <Kernel/Locking/Spinlock.h>
#include <Kernel/Memory/MemoryManager.h>

namespace Kernel::Graphics {

BootFramebufferConsole::BootFramebufferConsole(PhysicalAddress framebuffer_addr, size_t width, size_t height, size_t pitch)
    : GenericFramebufferConsoleImpl(width, height, pitch)
{
    // NOTE: We're very early in the boot process, memory allocations shouldn't really fail
    auto framebuffer_end = Memory::page_round_up(framebuffer_addr.offset(height * pitch * sizeof(u32)).get()).release_value();
    m_framebuffer = MM.allocate_kernel_region(framebuffer_addr.page_base(), framebuffer_end - framebuffer_addr.page_base().get(), "Boot Framebuffer"sv, Memory::Region::Access::ReadWrite).release_value();

    [[maybe_unused]] auto result = m_framebuffer->set_write_combine(true);
    m_framebuffer_data = m_framebuffer->vaddr().offset(framebuffer_addr.offset_in_page()).as_ptr();
    memset(m_framebuffer_data, 0, height * pitch * sizeof(u32));
}

void BootFramebufferConsole::clear(size_t x, size_t y, size_t length)
{
    SpinlockLocker lock(m_lock);
    if (m_framebuffer_data)
        GenericFramebufferConsoleImpl::clear(x, y, length);
}

void BootFramebufferConsole::clear_glyph(size_t x, size_t y)
{

    VERIFY(m_lock.is_locked());
    GenericFramebufferConsoleImpl::clear_glyph(x, y);
}

void BootFramebufferConsole::enable()
{
    // Once disabled, ignore requests to re-enable
}

void BootFramebufferConsole::disable()
{
    SpinlockLocker lock(m_lock);
    GenericFramebufferConsoleImpl::disable();
    m_framebuffer = nullptr;
    m_framebuffer_data = nullptr;
}

void BootFramebufferConsole::write(size_t x, size_t y, char ch, Color background, Color foreground, bool critical)
{
    SpinlockLocker lock(m_lock);
    if (m_framebuffer_data)
        GenericFramebufferConsoleImpl::write(x, y, ch, background, foreground, critical);
}

void BootFramebufferConsole::set_cursor(size_t x, size_t y)
{
    // Note: To ensure we don't trigger a deadlock, let's assert in
    // case we already locked the spinlock, so we know there's a bug
    // in the call path.
    VERIFY(!m_lock.is_locked());
    SpinlockLocker lock(m_lock);
    hide_cursor();
    m_x = x;
    m_y = y;
    show_cursor();
}

void BootFramebufferConsole::hide_cursor()
{
    VERIFY(m_lock.is_locked());
    GenericFramebufferConsoleImpl::hide_cursor();
}

void BootFramebufferConsole::show_cursor()
{
    VERIFY(m_lock.is_locked());
    GenericFramebufferConsoleImpl::show_cursor();
}

u8* BootFramebufferConsole::framebuffer_data()
{
    VERIFY(m_lock.is_locked());
    VERIFY(m_framebuffer_data);
    return m_framebuffer_data;
}

}