2021-03-05 14:23:08 +02:00
|
|
|
/*
|
|
|
|
|
* Copyright (c) 2021, Liav A. <liavalb@hotmail.co.il>
|
|
|
|
|
*
|
|
|
|
|
* SPDX-License-Identifier: BSD-2-Clause
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include <AK/Singleton.h>
|
2022-09-02 11:23:32 +03:00
|
|
|
#include <Kernel/Arch/Delay.h>
|
2022-09-16 13:17:02 +03:00
|
|
|
#if ARCH(I386) || ARCH(X86_64)
|
|
|
|
|
# include <Kernel/Arch/x86/Hypervisor/BochsDisplayConnector.h>
|
|
|
|
|
#endif
|
Kernel/PCI: Simplify the entire subsystem
A couple of things were changed:
1. Semantic changes - PCI segments are now called PCI domains, to better
match what they are really. It's also the name that Linux gave, and it
seems that Wikipedia also uses this name.
We also remove PCI::ChangeableAddress, because it was used in the past
but now it's no longer being used.
2. There are no WindowedMMIOAccess or MMIOAccess classes anymore, as
they made a bunch of unnecessary complexity. Instead, Windowed access is
removed entirely (this was tested, but never was benchmarked), so we are
left with IO access and memory access options. The memory access option
is essentially mapping the PCI bus (from the chosen PCI domain), to
virtual memory as-is. This means that unless needed, at any time, there
is only one PCI bus being mapped, and this is changed if access to
another PCI bus in the same PCI domain is needed. For now, we don't
support mapping of different PCI buses from different PCI domains at the
same time, because basically it's still a non-issue for most machines
out there.
2. OOM-safety is increased, especially when constructing the Access
object. It means that we pre-allocating any needed resources, and we try
to find PCI domains (if requested to initialize memory access) after we
attempt to construct the Access object, so it's possible to fail at this
point "gracefully".
3. All PCI API functions are now separated into a different header file,
which means only "clients" of the PCI subsystem API will need to include
that header file.
4. Functional changes - we only allow now to enumerate the bus after
a hardware scan. This means that the old method "enumerate_hardware"
is removed, so, when initializing an Access object, the initializing
function must call rescan on it to force it to find devices. This makes
it possible to fail rescan, and also to defer it after construction from
both OOM-safety terms and hotplug capabilities.
2021-09-07 12:08:38 +03:00
|
|
|
#include <Kernel/Bus/PCI/API.h>
|
2021-06-25 09:46:17 +03:00
|
|
|
#include <Kernel/Bus/PCI/IDs.h>
|
2021-03-05 14:23:08 +02:00
|
|
|
#include <Kernel/CommandLine.h>
|
2021-07-09 10:27:19 +03:00
|
|
|
#include <Kernel/Graphics/Bochs/GraphicsAdapter.h>
|
2022-01-29 14:08:05 -07:00
|
|
|
#include <Kernel/Graphics/Console/BootFramebufferConsole.h>
|
2021-03-05 14:23:08 +02:00
|
|
|
#include <Kernel/Graphics/GraphicsManagement.h>
|
2021-07-08 20:30:13 +03:00
|
|
|
#include <Kernel/Graphics/Intel/NativeGraphicsAdapter.h>
|
2022-03-18 16:46:55 +02:00
|
|
|
#include <Kernel/Graphics/VMWare/GraphicsAdapter.h>
|
2021-07-07 23:51:33 +10:00
|
|
|
#include <Kernel/Graphics/VirtIOGPU/GraphicsAdapter.h>
|
2021-08-06 10:45:34 +02:00
|
|
|
#include <Kernel/Memory/AnonymousVMObject.h>
|
2021-03-05 14:23:08 +02:00
|
|
|
#include <Kernel/Multiboot.h>
|
2021-06-22 17:40:16 +02:00
|
|
|
#include <Kernel/Sections.h>
|
2021-03-05 14:23:08 +02:00
|
|
|
|
|
|
|
|
namespace Kernel {
|
|
|
|
|
|
2021-08-07 21:34:11 +02:00
|
|
|
static Singleton<GraphicsManagement> s_the;
|
2021-03-05 14:23:08 +02:00
|
|
|
|
2022-02-09 21:09:41 +02:00
|
|
|
extern Atomic<Graphics::Console*> g_boot_console;
|
2022-01-29 14:08:05 -07:00
|
|
|
|
2021-03-05 14:23:08 +02:00
|
|
|
GraphicsManagement& GraphicsManagement::the()
|
|
|
|
|
{
|
|
|
|
|
return *s_the;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool GraphicsManagement::is_initialized()
|
|
|
|
|
{
|
|
|
|
|
return s_the.is_initialized();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
UNMAP_AFTER_INIT GraphicsManagement::GraphicsManagement()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2022-03-15 21:41:22 +02:00
|
|
|
void GraphicsManagement::disable_vga_emulation_access_permanently()
|
|
|
|
|
{
|
2022-09-23 11:06:14 +03:00
|
|
|
#if ARCH(I386) || ARCH(X86_64)
|
|
|
|
|
if (!m_vga_arbiter)
|
|
|
|
|
return;
|
|
|
|
|
m_vga_arbiter->disable_vga_emulation_access_permanently({});
|
|
|
|
|
#endif
|
2022-03-15 21:41:22 +02:00
|
|
|
}
|
|
|
|
|
|
2022-03-18 11:58:34 +02:00
|
|
|
void GraphicsManagement::enable_vga_text_mode_console_cursor()
|
2022-03-15 21:41:22 +02:00
|
|
|
{
|
2022-09-23 11:06:14 +03:00
|
|
|
#if ARCH(I386) || ARCH(X86_64)
|
|
|
|
|
if (!m_vga_arbiter)
|
2022-03-15 21:41:22 +02:00
|
|
|
return;
|
2022-09-23 11:06:14 +03:00
|
|
|
m_vga_arbiter->enable_vga_text_mode_console_cursor({});
|
|
|
|
|
#endif
|
2022-03-15 21:41:22 +02:00
|
|
|
}
|
|
|
|
|
|
2022-03-18 11:58:34 +02:00
|
|
|
void GraphicsManagement::disable_vga_text_mode_console_cursor()
|
2022-03-15 21:41:22 +02:00
|
|
|
{
|
2022-09-23 11:06:14 +03:00
|
|
|
#if ARCH(I386) || ARCH(X86_64)
|
|
|
|
|
if (!m_vga_arbiter)
|
2022-03-15 21:41:22 +02:00
|
|
|
return;
|
2022-09-23 11:06:14 +03:00
|
|
|
m_vga_arbiter->disable_vga_text_mode_console_cursor({});
|
|
|
|
|
#endif
|
2022-03-15 21:41:22 +02:00
|
|
|
}
|
|
|
|
|
|
2022-09-23 11:06:14 +03:00
|
|
|
void GraphicsManagement::set_vga_text_mode_cursor([[maybe_unused]] size_t console_width, [[maybe_unused]] size_t x, [[maybe_unused]] size_t y)
|
2022-03-15 21:41:22 +02:00
|
|
|
{
|
2022-09-23 11:06:14 +03:00
|
|
|
#if ARCH(I386) || ARCH(X86_64)
|
|
|
|
|
if (!m_vga_arbiter)
|
2022-03-15 21:41:22 +02:00
|
|
|
return;
|
2022-09-23 11:06:14 +03:00
|
|
|
m_vga_arbiter->set_vga_text_mode_cursor({}, console_width, x, y);
|
|
|
|
|
#endif
|
2022-03-15 21:41:22 +02:00
|
|
|
}
|
|
|
|
|
|
2021-04-16 22:58:51 +03:00
|
|
|
void GraphicsManagement::deactivate_graphical_mode()
|
|
|
|
|
{
|
2022-05-06 14:46:58 +03:00
|
|
|
return m_display_connector_nodes.with([&](auto& display_connectors) {
|
|
|
|
|
for (auto& connector : display_connectors)
|
|
|
|
|
connector.set_display_mode({}, DisplayConnector::DisplayMode::Console);
|
|
|
|
|
});
|
2021-04-16 22:58:51 +03:00
|
|
|
}
|
|
|
|
|
void GraphicsManagement::activate_graphical_mode()
|
|
|
|
|
{
|
2022-05-06 14:46:58 +03:00
|
|
|
return m_display_connector_nodes.with([&](auto& display_connectors) {
|
|
|
|
|
for (auto& connector : display_connectors)
|
|
|
|
|
connector.set_display_mode({}, DisplayConnector::DisplayMode::Graphical);
|
|
|
|
|
});
|
Kernel/Graphics: Introduce the DisplayConnector class
The DisplayConnector class is meant to replace the FramebufferDevice
class. The advantage of this class over the FramebufferDevice class is:
1. It removes the mmap interface entirely. This interface is unsafe, as
multiple processes could try to use it, and when switching to and from
text console mode, there's no "good" way to revoke a memory mapping from
this interface, let alone when there are multiple processes that call
this interface. Therefore, in the DisplayConnector class there's no
implementation for this method at all.
2. The class uses a new real-world structure called ModeSetting, which
takes into account the fact that real hardware requires more than width,
height and pitch settings to mode-set the display resolution.
3. The class assumes all instances should supply some sort of EDID,
so it facilitates such mechanism to do so. Even if a given driver does
not know what is the actual EDID, it will ask to create default-generic
EDID blob.
3. This class shifts the responsibilies of switching between console
mode and graphical mode from a GraphicsAdapter to the DisplayConnector
class, so when doing the switch, the GraphicsManagement code actually
asks each DisplayConnector object to do the switch and doesn't rely on
the GraphicsAdapter objects at all.
2022-04-29 12:44:46 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void GraphicsManagement::attach_new_display_connector(Badge<DisplayConnector>, DisplayConnector& connector)
|
|
|
|
|
{
|
2022-05-06 14:46:58 +03:00
|
|
|
return m_display_connector_nodes.with([&](auto& display_connectors) {
|
|
|
|
|
display_connectors.append(connector);
|
|
|
|
|
});
|
Kernel/Graphics: Introduce the DisplayConnector class
The DisplayConnector class is meant to replace the FramebufferDevice
class. The advantage of this class over the FramebufferDevice class is:
1. It removes the mmap interface entirely. This interface is unsafe, as
multiple processes could try to use it, and when switching to and from
text console mode, there's no "good" way to revoke a memory mapping from
this interface, let alone when there are multiple processes that call
this interface. Therefore, in the DisplayConnector class there's no
implementation for this method at all.
2. The class uses a new real-world structure called ModeSetting, which
takes into account the fact that real hardware requires more than width,
height and pitch settings to mode-set the display resolution.
3. The class assumes all instances should supply some sort of EDID,
so it facilitates such mechanism to do so. Even if a given driver does
not know what is the actual EDID, it will ask to create default-generic
EDID blob.
3. This class shifts the responsibilies of switching between console
mode and graphical mode from a GraphicsAdapter to the DisplayConnector
class, so when doing the switch, the GraphicsManagement code actually
asks each DisplayConnector object to do the switch and doesn't rely on
the GraphicsAdapter objects at all.
2022-04-29 12:44:46 +03:00
|
|
|
}
|
|
|
|
|
void GraphicsManagement::detach_display_connector(Badge<DisplayConnector>, DisplayConnector& connector)
|
|
|
|
|
{
|
2022-05-06 14:46:58 +03:00
|
|
|
return m_display_connector_nodes.with([&](auto& display_connectors) {
|
|
|
|
|
display_connectors.remove(connector);
|
|
|
|
|
});
|
2021-04-16 22:58:51 +03:00
|
|
|
}
|
|
|
|
|
|
2021-09-23 10:20:54 +03:00
|
|
|
static inline bool is_vga_compatible_pci_device(PCI::DeviceIdentifier const& device_identifier)
|
2021-03-05 14:23:08 +02:00
|
|
|
{
|
2021-07-03 05:04:02 +03:00
|
|
|
// Note: Check for Display Controller, VGA Compatible Controller or
|
|
|
|
|
// Unclassified, VGA-Compatible Unclassified Device
|
2021-09-23 10:20:54 +03:00
|
|
|
auto is_display_controller_vga_compatible = device_identifier.class_code().value() == 0x3 && device_identifier.subclass_code().value() == 0x0;
|
|
|
|
|
auto is_general_pci_vga_compatible = device_identifier.class_code().value() == 0x0 && device_identifier.subclass_code().value() == 0x1;
|
2021-07-03 05:04:02 +03:00
|
|
|
return is_display_controller_vga_compatible || is_general_pci_vga_compatible;
|
|
|
|
|
}
|
|
|
|
|
|
2021-09-23 10:20:54 +03:00
|
|
|
static inline bool is_display_controller_pci_device(PCI::DeviceIdentifier const& device_identifier)
|
2021-07-03 05:04:02 +03:00
|
|
|
{
|
2021-09-23 10:20:54 +03:00
|
|
|
return device_identifier.class_code().value() == 0x3;
|
2021-07-03 05:04:02 +03:00
|
|
|
}
|
|
|
|
|
|
2021-09-23 10:20:54 +03:00
|
|
|
UNMAP_AFTER_INIT bool GraphicsManagement::determine_and_initialize_graphics_device(PCI::DeviceIdentifier const& device_identifier)
|
2021-07-03 05:04:02 +03:00
|
|
|
{
|
2021-09-23 10:20:54 +03:00
|
|
|
VERIFY(is_vga_compatible_pci_device(device_identifier) || is_display_controller_pci_device(device_identifier));
|
2022-08-19 20:53:40 +02:00
|
|
|
LockRefPtr<GenericGraphicsAdapter> adapter;
|
2022-01-05 14:45:29 -07:00
|
|
|
|
|
|
|
|
if (!adapter) {
|
|
|
|
|
switch (device_identifier.hardware_id().vendor_id) {
|
|
|
|
|
case PCI::VendorID::QEMUOld:
|
|
|
|
|
if (device_identifier.hardware_id().device_id == 0x1111)
|
|
|
|
|
adapter = BochsGraphicsAdapter::initialize(device_identifier);
|
|
|
|
|
break;
|
|
|
|
|
case PCI::VendorID::VirtualBox:
|
|
|
|
|
if (device_identifier.hardware_id().device_id == 0xbeef)
|
|
|
|
|
adapter = BochsGraphicsAdapter::initialize(device_identifier);
|
|
|
|
|
break;
|
|
|
|
|
case PCI::VendorID::Intel:
|
|
|
|
|
adapter = IntelNativeGraphicsAdapter::initialize(device_identifier);
|
2021-07-03 05:04:02 +03:00
|
|
|
break;
|
2022-01-05 14:45:29 -07:00
|
|
|
case PCI::VendorID::VirtIO:
|
|
|
|
|
dmesgln("Graphics: Using VirtIO console");
|
2022-04-30 13:56:29 +03:00
|
|
|
adapter = VirtIOGraphicsAdapter::initialize(device_identifier);
|
2022-01-05 14:45:29 -07:00
|
|
|
break;
|
2022-03-18 16:46:55 +02:00
|
|
|
case PCI::VendorID::VMWare:
|
|
|
|
|
adapter = VMWareGraphicsAdapter::try_initialize(device_identifier);
|
|
|
|
|
break;
|
2022-01-05 14:45:29 -07:00
|
|
|
default:
|
|
|
|
|
break;
|
2021-07-03 05:04:02 +03:00
|
|
|
}
|
|
|
|
|
}
|
2022-01-05 14:45:29 -07:00
|
|
|
|
2021-07-03 05:04:02 +03:00
|
|
|
if (!adapter)
|
|
|
|
|
return false;
|
2022-04-30 15:54:23 +03:00
|
|
|
m_graphics_devices.append(*adapter);
|
2021-07-03 05:04:02 +03:00
|
|
|
return true;
|
2021-03-05 14:23:08 +02:00
|
|
|
}
|
|
|
|
|
|
2022-07-09 08:58:57 +03:00
|
|
|
UNMAP_AFTER_INIT void GraphicsManagement::initialize_preset_resolution_generic_display_connector()
|
|
|
|
|
{
|
|
|
|
|
VERIFY(!multiboot_framebuffer_addr.is_null());
|
|
|
|
|
VERIFY(multiboot_framebuffer_type == MULTIBOOT_FRAMEBUFFER_TYPE_RGB);
|
|
|
|
|
dmesgln("Graphics: Using a preset resolution from the bootloader, without knowing the PCI device");
|
|
|
|
|
m_preset_resolution_generic_display_connector = GenericDisplayConnector::must_create_with_preset_resolution(
|
|
|
|
|
multiboot_framebuffer_addr,
|
|
|
|
|
multiboot_framebuffer_width,
|
|
|
|
|
multiboot_framebuffer_height,
|
|
|
|
|
multiboot_framebuffer_pitch);
|
|
|
|
|
}
|
|
|
|
|
|
2021-03-05 14:23:08 +02:00
|
|
|
UNMAP_AFTER_INIT bool GraphicsManagement::initialize()
|
|
|
|
|
{
|
2021-04-16 22:58:51 +03:00
|
|
|
|
2022-07-09 09:13:00 +03:00
|
|
|
/* Explanation on the flow here:
|
2022-01-21 16:15:46 +02:00
|
|
|
*
|
2022-07-09 09:13:00 +03:00
|
|
|
* If the user chose to disable graphics support entirely, then all we can do
|
|
|
|
|
* is to set up a plain old VGA text console and exit this function.
|
|
|
|
|
* Otherwise, we either try to find a device that we natively support so
|
|
|
|
|
* we can initialize it, and in case we don't find any device to initialize,
|
|
|
|
|
* we try to initialize a simple DisplayConnector to support a pre-initialized
|
|
|
|
|
* framebuffer.
|
2022-01-21 16:15:46 +02:00
|
|
|
*
|
2022-07-09 09:13:00 +03:00
|
|
|
* Note: If the user disabled PCI access, the kernel behaves like it's running
|
2022-01-21 16:15:46 +02:00
|
|
|
* on a pure ISA PC machine and therefore the kernel will try to initialize
|
|
|
|
|
* a variant that is suitable for ISA VGA handling, and not PCI adapters.
|
2021-04-16 22:58:51 +03:00
|
|
|
*/
|
|
|
|
|
|
2022-09-16 13:10:06 +03:00
|
|
|
ScopeGuard assign_console_on_initialization_exit([this] {
|
|
|
|
|
if (!m_console) {
|
|
|
|
|
// If no graphics driver was instantiated and we had a bootloader provided
|
|
|
|
|
// framebuffer console we can simply re-use it.
|
|
|
|
|
if (auto* boot_console = g_boot_console.load()) {
|
|
|
|
|
m_console = *boot_console;
|
|
|
|
|
boot_console->unref(); // Drop the leaked reference from Kernel::init()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
2022-09-23 11:06:14 +03:00
|
|
|
#if ARCH(I386) || ARCH(X86_64)
|
|
|
|
|
m_vga_arbiter = VGAIOArbiter::must_create({});
|
|
|
|
|
#endif
|
2022-09-16 13:10:06 +03:00
|
|
|
|
2022-04-30 15:53:02 +03:00
|
|
|
auto graphics_subsystem_mode = kernel_command_line().graphics_subsystem_mode();
|
2022-05-06 01:03:18 +03:00
|
|
|
if (graphics_subsystem_mode == CommandLine::GraphicsSubsystemMode::Disabled) {
|
|
|
|
|
VERIFY(!m_console);
|
2022-04-30 15:53:02 +03:00
|
|
|
return true;
|
2022-05-06 01:03:18 +03:00
|
|
|
}
|
2022-04-30 15:53:02 +03:00
|
|
|
|
2022-09-16 13:17:02 +03:00
|
|
|
// Note: Don't try to initialize an ISA Bochs VGA adapter if PCI hardware is
|
|
|
|
|
// present but the user decided to disable its usage nevertheless.
|
|
|
|
|
// Otherwise we risk using the Bochs VBE driver on a wrong physical address
|
|
|
|
|
// for the framebuffer.
|
|
|
|
|
if (PCI::Access::is_hardware_disabled() && !(graphics_subsystem_mode == CommandLine::GraphicsSubsystemMode::Limited && !multiboot_framebuffer_addr.is_null() && multiboot_framebuffer_type == MULTIBOOT_FRAMEBUFFER_TYPE_RGB)) {
|
|
|
|
|
#if ARCH(I386) || ARCH(X86_64)
|
|
|
|
|
auto vga_isa_bochs_display_connector = BochsDisplayConnector::try_create_for_vga_isa_connector();
|
|
|
|
|
if (vga_isa_bochs_display_connector) {
|
|
|
|
|
dmesgln("Graphics: Using a Bochs ISA VGA compatible adapter");
|
|
|
|
|
MUST(vga_isa_bochs_display_connector->set_safe_mode_setting());
|
|
|
|
|
m_platform_board_specific_display_connector = vga_isa_bochs_display_connector;
|
|
|
|
|
dmesgln("Graphics: Invoking manual blanking with VGA ISA ports");
|
2022-09-23 11:06:14 +03:00
|
|
|
m_vga_arbiter->unblank_screen({});
|
2022-09-16 13:17:02 +03:00
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
2022-07-09 09:11:03 +03:00
|
|
|
if (graphics_subsystem_mode == CommandLine::GraphicsSubsystemMode::Limited && !multiboot_framebuffer_addr.is_null() && multiboot_framebuffer_type == MULTIBOOT_FRAMEBUFFER_TYPE_RGB) {
|
2022-07-09 08:58:57 +03:00
|
|
|
initialize_preset_resolution_generic_display_connector();
|
2022-04-30 15:53:02 +03:00
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2022-01-21 16:15:46 +02:00
|
|
|
if (PCI::Access::is_disabled()) {
|
2022-07-09 08:58:57 +03:00
|
|
|
dmesgln("Graphics: Using an assumed-to-exist ISA VGA compatible generic adapter");
|
2022-01-21 16:15:46 +02:00
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2022-02-04 19:48:13 +02:00
|
|
|
MUST(PCI::enumerate([&](PCI::DeviceIdentifier const& device_identifier) {
|
2021-06-16 19:35:11 -06:00
|
|
|
// Note: Each graphics controller will try to set its native screen resolution
|
|
|
|
|
// upon creation. Later on, if we don't want to have framebuffer devices, a
|
|
|
|
|
// framebuffer console will take the control instead.
|
2021-09-23 10:20:54 +03:00
|
|
|
if (!is_vga_compatible_pci_device(device_identifier) && !is_display_controller_pci_device(device_identifier))
|
2021-07-03 05:04:02 +03:00
|
|
|
return;
|
2021-09-23 10:20:54 +03:00
|
|
|
determine_and_initialize_graphics_device(device_identifier);
|
2022-02-04 19:48:13 +02:00
|
|
|
}));
|
2021-06-16 19:35:11 -06:00
|
|
|
|
2022-07-09 08:58:57 +03:00
|
|
|
// Note: If we failed to find any graphics device to be used natively, but the
|
|
|
|
|
// bootloader prepared a framebuffer for us to use, then just create a DisplayConnector
|
|
|
|
|
// for it so the user can still use the system in graphics mode.
|
|
|
|
|
// Prekernel sets the framebuffer address to 0 if MULTIBOOT_INFO_FRAMEBUFFER_INFO
|
|
|
|
|
// is not present, as there is likely never a valid framebuffer at this physical address.
|
|
|
|
|
// Note: We only support RGB framebuffers. Any other format besides RGBX (and RGBA) or BGRX (and BGRA) is obsolete
|
|
|
|
|
// and is not useful for us.
|
|
|
|
|
if (m_graphics_devices.is_empty() && !multiboot_framebuffer_addr.is_null() && multiboot_framebuffer_type == MULTIBOOT_FRAMEBUFFER_TYPE_RGB) {
|
|
|
|
|
initialize_preset_resolution_generic_display_connector();
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2021-05-21 11:23:41 +03:00
|
|
|
if (m_graphics_devices.is_empty()) {
|
|
|
|
|
dbgln("No graphics adapter was initialized.");
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2021-03-05 14:23:08 +02:00
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2022-01-29 14:08:05 -07:00
|
|
|
void GraphicsManagement::set_console(Graphics::Console& console)
|
|
|
|
|
{
|
|
|
|
|
m_console = console;
|
|
|
|
|
|
2022-02-09 21:09:41 +02:00
|
|
|
if (auto* boot_console = g_boot_console.exchange(nullptr)) {
|
2022-01-29 14:08:05 -07:00
|
|
|
// Disable the initial boot framebuffer console permanently
|
|
|
|
|
boot_console->disable();
|
|
|
|
|
// TODO: Even though we swapped the pointer and disabled the console
|
|
|
|
|
// we technically can't safely destroy it as other CPUs might still
|
|
|
|
|
// try to use it. Once we solve this problem we can drop the reference
|
|
|
|
|
// that we intentionally leaked in Kernel::init().
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-03-05 14:23:08 +02:00
|
|
|
}
|