Skip to content

Commit 785c10f

Browse files
tomutalinusg
authored andcommitted
Kernel: Add option to force using only the bootloader framebuffer
This allows forcing the use of only the framebuffer set up by the bootloader and skips instantiating devices for any other graphics cards that may be present.
1 parent 01b3666 commit 785c10f

File tree

5 files changed

+83
-53
lines changed

5 files changed

+83
-53
lines changed

Base/usr/share/man/man7/boot_parameters.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ List of options:
4141
but only if **`acpi`** is set to **`limited`** or **`on`**, and a `MADT` (APIC) table is available.
4242
Otherwise, the kernel will fallback to use the i8259 PICs.
4343

44-
* **`fbdev`** - This parameter expects **`on`** or **`off`**.
44+
* **`fbdev`** - This parameter expects one of the following values. **`on`**- Boot into the graphical environment (default). **`off`** - Boot into text mode. **`bootloader`** - Boot into the graphical environment, but only use the frame buffer set up by the bootloader and do not initialize any other graphics cards.
4545

4646
* **`force_pio`** - If present on the command line, the IDE controllers will be force into PIO mode when initialized IDE Channels on boot.
4747

Kernel/CommandLine.cpp

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -245,9 +245,14 @@ PanicMode CommandLine::panic_mode(Validate should_validate) const
245245
return PanicMode::Halt;
246246
}
247247

248-
UNMAP_AFTER_INIT bool CommandLine::are_framebuffer_devices_enabled() const
249-
{
250-
return lookup("fbdev"sv).value_or("on"sv) == "on"sv;
248+
UNMAP_AFTER_INIT auto CommandLine::are_framebuffer_devices_enabled() const -> FrameBufferDevices
249+
{
250+
const auto fbdev_value = lookup("fbdev"sv).value_or("on"sv);
251+
if (fbdev_value == "on"sv)
252+
return FrameBufferDevices::Enabled;
253+
if (fbdev_value == "bootloader"sv)
254+
return FrameBufferDevices::BootloaderOnly;
255+
return FrameBufferDevices::ConsoleOnly;
251256
}
252257

253258
StringView CommandLine::userspace_init() const

Kernel/CommandLine.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,12 @@ class CommandLine {
5252
No,
5353
};
5454

55+
enum class FrameBufferDevices {
56+
Enabled,
57+
ConsoleOnly,
58+
BootloaderOnly
59+
};
60+
5561
[[nodiscard]] const String& string() const { return m_string; }
5662
Optional<StringView> lookup(StringView key) const;
5763
[[nodiscard]] bool contains(StringView key) const;
@@ -65,7 +71,7 @@ class CommandLine {
6571
[[nodiscard]] bool is_vmmouse_enabled() const;
6672
[[nodiscard]] PCIAccessLevel pci_access_level() const;
6773
[[nodiscard]] bool is_legacy_time_enabled() const;
68-
[[nodiscard]] bool are_framebuffer_devices_enabled() const;
74+
[[nodiscard]] FrameBufferDevices are_framebuffer_devices_enabled() const;
6975
[[nodiscard]] bool is_force_pio() const;
7076
[[nodiscard]] AcpiFeatureLevel acpi_feature_level() const;
7177
[[nodiscard]] StringView system_mode() const;

Kernel/Graphics/GraphicsManagement.cpp

Lines changed: 65 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,14 @@ UNMAP_AFTER_INIT GraphicsManagement::GraphicsManagement()
3636
{
3737
}
3838

39-
bool GraphicsManagement::framebuffer_devices_allowed() const
39+
bool GraphicsManagement::framebuffer_devices_use_bootloader_framebuffer() const
4040
{
41-
return kernel_command_line().are_framebuffer_devices_enabled();
41+
return kernel_command_line().are_framebuffer_devices_enabled() == CommandLine::FrameBufferDevices::BootloaderOnly;
42+
}
43+
44+
bool GraphicsManagement::framebuffer_devices_console_only() const
45+
{
46+
return kernel_command_line().are_framebuffer_devices_enabled() == CommandLine::FrameBufferDevices::ConsoleOnly;
4247
}
4348

4449
void GraphicsManagement::deactivate_graphical_mode()
@@ -73,60 +78,71 @@ UNMAP_AFTER_INIT bool GraphicsManagement::determine_and_initialize_graphics_devi
7378
VERIFY(is_vga_compatible_pci_device(device_identifier) || is_display_controller_pci_device(device_identifier));
7479
auto add_and_configure_adapter = [&](GenericGraphicsAdapter& graphics_device) {
7580
m_graphics_devices.append(graphics_device);
76-
if (!framebuffer_devices_allowed()) {
81+
if (framebuffer_devices_console_only()) {
7782
graphics_device.enable_consoles();
7883
return;
7984
}
8085
graphics_device.initialize_framebuffer_devices();
8186
};
8287

8388
RefPtr<GenericGraphicsAdapter> adapter;
84-
switch (device_identifier.hardware_id().vendor_id) {
85-
case PCI::VendorID::QEMUOld:
86-
if (device_identifier.hardware_id().device_id == 0x1111)
87-
adapter = BochsGraphicsAdapter::initialize(device_identifier);
88-
break;
89-
case PCI::VendorID::VirtualBox:
90-
if (device_identifier.hardware_id().device_id == 0xbeef)
91-
adapter = BochsGraphicsAdapter::initialize(device_identifier);
92-
break;
93-
case PCI::VendorID::Intel:
94-
adapter = IntelNativeGraphicsAdapter::initialize(device_identifier);
95-
break;
96-
case PCI::VendorID::VirtIO:
97-
dmesgln("Graphics: Using VirtIO console");
98-
adapter = Graphics::VirtIOGPU::GraphicsAdapter::initialize(device_identifier);
99-
break;
100-
default:
101-
if (!is_vga_compatible_pci_device(device_identifier))
89+
90+
auto create_bootloader_framebuffer_device = [&]() {
91+
if (multiboot_framebuffer_type == MULTIBOOT_FRAMEBUFFER_TYPE_RGB) {
92+
dmesgln("Graphics: Using a preset resolution from the bootloader");
93+
adapter = VGACompatibleAdapter::initialize_with_preset_resolution(device_identifier,
94+
multiboot_framebuffer_addr,
95+
multiboot_framebuffer_width,
96+
multiboot_framebuffer_height,
97+
multiboot_framebuffer_pitch);
98+
}
99+
};
100+
101+
if (framebuffer_devices_use_bootloader_framebuffer())
102+
create_bootloader_framebuffer_device();
103+
104+
if (!adapter) {
105+
switch (device_identifier.hardware_id().vendor_id) {
106+
case PCI::VendorID::QEMUOld:
107+
if (device_identifier.hardware_id().device_id == 0x1111)
108+
adapter = BochsGraphicsAdapter::initialize(device_identifier);
109+
break;
110+
case PCI::VendorID::VirtualBox:
111+
if (device_identifier.hardware_id().device_id == 0xbeef)
112+
adapter = BochsGraphicsAdapter::initialize(device_identifier);
113+
break;
114+
case PCI::VendorID::Intel:
115+
adapter = IntelNativeGraphicsAdapter::initialize(device_identifier);
102116
break;
103-
// Note: Although technically possible that a system has a
104-
// non-compatible VGA graphics device that was initialized by the
105-
// Multiboot bootloader to provide a framebuffer, in practice we
106-
// probably want to support these devices natively instead of
107-
// initializing them as some sort of a generic GenericGraphicsAdapter. For now,
108-
// the only known example of this sort of device is qxl in QEMU. For VGA
109-
// compatible devices we don't have a special driver for (e.g. ati-vga,
110-
// qxl-vga, cirrus-vga, vmware-svga in QEMU), it's much more likely that
111-
// these devices will be supported by the Multiboot loader that will
112-
// utilize VESA BIOS extensions (that we don't currently) of these cards
113-
// support, so we want to utilize the provided framebuffer of these
114-
// devices, if possible.
115-
if (!m_vga_adapter && PCI::is_io_space_enabled(device_identifier.address())) {
116-
if (multiboot_framebuffer_type == MULTIBOOT_FRAMEBUFFER_TYPE_RGB) {
117-
dmesgln("Graphics: Using a preset resolution from the bootloader");
118-
adapter = VGACompatibleAdapter::initialize_with_preset_resolution(device_identifier,
119-
multiboot_framebuffer_addr,
120-
multiboot_framebuffer_width,
121-
multiboot_framebuffer_height,
122-
multiboot_framebuffer_pitch);
117+
case PCI::VendorID::VirtIO:
118+
dmesgln("Graphics: Using VirtIO console");
119+
adapter = Graphics::VirtIOGPU::GraphicsAdapter::initialize(device_identifier);
120+
break;
121+
default:
122+
if (!is_vga_compatible_pci_device(device_identifier))
123+
break;
124+
// Note: Although technically possible that a system has a
125+
// non-compatible VGA graphics device that was initialized by the
126+
// Multiboot bootloader to provide a framebuffer, in practice we
127+
// probably want to support these devices natively instead of
128+
// initializing them as some sort of a generic GenericGraphicsAdapter. For now,
129+
// the only known example of this sort of device is qxl in QEMU. For VGA
130+
// compatible devices we don't have a special driver for (e.g. ati-vga,
131+
// qxl-vga, cirrus-vga, vmware-svga in QEMU), it's much more likely that
132+
// these devices will be supported by the Multiboot loader that will
133+
// utilize VESA BIOS extensions (that we don't currently) of these cards
134+
// support, so we want to utilize the provided framebuffer of these
135+
// devices, if possible.
136+
if (!m_vga_adapter && PCI::is_io_space_enabled(device_identifier.address())) {
137+
create_bootloader_framebuffer_device();
138+
} else {
139+
dmesgln("Graphics: Using a VGA compatible generic adapter");
140+
adapter = VGACompatibleAdapter::initialize(device_identifier);
123141
}
124-
} else {
125-
dmesgln("Graphics: Using a VGA compatible generic adapter");
126-
adapter = VGACompatibleAdapter::initialize(device_identifier);
142+
break;
127143
}
128-
break;
129144
}
145+
130146
if (!adapter)
131147
return false;
132148
add_and_configure_adapter(*adapter);
@@ -179,8 +195,10 @@ UNMAP_AFTER_INIT bool GraphicsManagement::initialize()
179195
* be created, so SystemServer will not try to initialize WindowServer.
180196
*/
181197

182-
if (!framebuffer_devices_allowed())
183-
dbgln("Forcing non-initialization of framebuffer devices");
198+
if (framebuffer_devices_console_only())
199+
dbgln("Forcing non-initialization of framebuffer devices (console only)");
200+
else if (framebuffer_devices_use_bootloader_framebuffer())
201+
dbgln("Forcing use of framebuffer set up by the bootloader");
184202

185203
PCI::enumerate([&](PCI::DeviceIdentifier const& device_identifier) {
186204
// Note: Each graphics controller will try to set its native screen resolution

Kernel/Graphics/GraphicsManagement.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,8 @@ class GraphicsManagement {
3636
unsigned allocate_minor_device_number() { return m_current_minor_number++; };
3737
GraphicsManagement();
3838

39-
bool framebuffer_devices_allowed() const;
39+
bool framebuffer_devices_console_only() const;
40+
bool framebuffer_devices_use_bootloader_framebuffer() const;
4041
bool framebuffer_devices_exist() const;
4142

4243
Spinlock& main_vga_lock() { return m_main_vga_lock; }

0 commit comments

Comments
 (0)