Serenity Operating System
1/*
2 * Copyright (c) 2022, the SerenityOS developers.
3 *
4 * SPDX-License-Identifier: BSD-2-Clause
5 */
6
7#include <Kernel/Graphics/Console/BootFramebufferConsole.h>
8#include <Kernel/Locking/Spinlock.h>
9#include <Kernel/Memory/MemoryManager.h>
10
11namespace Kernel::Graphics {
12
13BootFramebufferConsole::BootFramebufferConsole(PhysicalAddress framebuffer_addr, size_t width, size_t height, size_t pitch)
14 : GenericFramebufferConsoleImpl(width, height, pitch)
15{
16 // NOTE: We're very early in the boot process, memory allocations shouldn't really fail
17 auto framebuffer_end = Memory::page_round_up(framebuffer_addr.offset(height * pitch * sizeof(u32)).get()).release_value();
18 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();
19
20 [[maybe_unused]] auto result = m_framebuffer->set_write_combine(true);
21 m_framebuffer_data = m_framebuffer->vaddr().offset(framebuffer_addr.offset_in_page()).as_ptr();
22 memset(m_framebuffer_data, 0, height * pitch * sizeof(u32));
23}
24
25void BootFramebufferConsole::clear(size_t x, size_t y, size_t length)
26{
27 SpinlockLocker lock(m_lock);
28 if (m_framebuffer_data)
29 GenericFramebufferConsoleImpl::clear(x, y, length);
30}
31
32void BootFramebufferConsole::clear_glyph(size_t x, size_t y)
33{
34
35 VERIFY(m_lock.is_locked());
36 GenericFramebufferConsoleImpl::clear_glyph(x, y);
37}
38
39void BootFramebufferConsole::enable()
40{
41 // Once disabled, ignore requests to re-enable
42}
43
44void BootFramebufferConsole::disable()
45{
46 SpinlockLocker lock(m_lock);
47 GenericFramebufferConsoleImpl::disable();
48 m_framebuffer = nullptr;
49 m_framebuffer_data = nullptr;
50}
51
52void BootFramebufferConsole::write(size_t x, size_t y, char ch, Color background, Color foreground, bool critical)
53{
54 SpinlockLocker lock(m_lock);
55 if (m_framebuffer_data)
56 GenericFramebufferConsoleImpl::write(x, y, ch, background, foreground, critical);
57}
58
59void BootFramebufferConsole::set_cursor(size_t x, size_t y)
60{
61 // Note: To ensure we don't trigger a deadlock, let's assert in
62 // case we already locked the spinlock, so we know there's a bug
63 // in the call path.
64 VERIFY(!m_lock.is_locked());
65 SpinlockLocker lock(m_lock);
66 hide_cursor();
67 m_x = x;
68 m_y = y;
69 show_cursor();
70}
71
72void BootFramebufferConsole::hide_cursor()
73{
74 VERIFY(m_lock.is_locked());
75 GenericFramebufferConsoleImpl::hide_cursor();
76}
77
78void BootFramebufferConsole::show_cursor()
79{
80 VERIFY(m_lock.is_locked());
81 GenericFramebufferConsoleImpl::show_cursor();
82}
83
84u8* BootFramebufferConsole::framebuffer_data()
85{
86 VERIFY(m_lock.is_locked());
87 VERIFY(m_framebuffer_data);
88 return m_framebuffer_data;
89}
90
91}