diff options
-rw-r--r-- | Kernel/CMakeLists.txt | 8 | ||||
-rw-r--r-- | Kernel/Devices/BXVGADevice.cpp | 290 | ||||
-rw-r--r-- | Kernel/Devices/BXVGADevice.h | 64 | ||||
-rw-r--r-- | Kernel/Graphics/Bochs.h | 27 | ||||
-rw-r--r-- | Kernel/Graphics/BochsFramebufferDevice.cpp | 114 | ||||
-rw-r--r-- | Kernel/Graphics/BochsFramebufferDevice.h | 41 | ||||
-rw-r--r-- | Kernel/Graphics/BochsGraphicsAdapter.cpp | 126 | ||||
-rw-r--r-- | Kernel/Graphics/BochsGraphicsAdapter.h | 49 | ||||
-rw-r--r-- | Kernel/Graphics/FramebufferDevice.cpp (renamed from Kernel/Devices/MBVGADevice.cpp) | 64 | ||||
-rw-r--r-- | Kernel/Graphics/FramebufferDevice.h (renamed from Kernel/Devices/MBVGADevice.h) | 29 | ||||
-rw-r--r-- | Kernel/Graphics/GraphicsDevice.h | 33 | ||||
-rw-r--r-- | Kernel/Graphics/GraphicsManagement.cpp | 68 | ||||
-rw-r--r-- | Kernel/Graphics/GraphicsManagement.h | 38 | ||||
-rw-r--r-- | Kernel/Graphics/RawFramebufferDevice.cpp | 20 | ||||
-rw-r--r-- | Kernel/Graphics/RawFramebufferDevice.h | 31 | ||||
-rw-r--r-- | Kernel/Graphics/VGACompatibleAdapter.cpp | 31 | ||||
-rw-r--r-- | Kernel/Graphics/VGACompatibleAdapter.h | 38 | ||||
-rw-r--r-- | Kernel/init.cpp | 31 |
18 files changed, 673 insertions, 429 deletions
diff --git a/Kernel/CMakeLists.txt b/Kernel/CMakeLists.txt index 103ba80609..e0e6be75d8 100644 --- a/Kernel/CMakeLists.txt +++ b/Kernel/CMakeLists.txt @@ -27,12 +27,10 @@ set(KERNEL_SOURCES CoreDump.cpp DMI.cpp Devices/AsyncDeviceRequest.cpp - Devices/BXVGADevice.cpp Devices/BlockDevice.cpp Devices/CharacterDevice.cpp Devices/Device.cpp Devices/FullDevice.cpp - Devices/MBVGADevice.cpp Devices/MemoryDevice.cpp Devices/NullDevice.cpp Devices/PCSpeaker.cpp @@ -52,6 +50,12 @@ set(KERNEL_SOURCES Devices/HID/PS2KeyboardDevice.cpp Devices/HID/PS2MouseDevice.cpp Devices/HID/VMWareMouseDevice.cpp + Graphics/BochsFramebufferDevice.cpp + Graphics/BochsGraphicsAdapter.cpp + Graphics/FramebufferDevice.cpp + Graphics/GraphicsManagement.cpp + Graphics/RawFramebufferDevice.cpp + Graphics/VGACompatibleAdapter.cpp Storage/Partition/DiskPartition.cpp Storage/Partition/DiskPartitionMetadata.cpp Storage/Partition/EBRPartitionTable.cpp diff --git a/Kernel/Devices/BXVGADevice.cpp b/Kernel/Devices/BXVGADevice.cpp deleted file mode 100644 index 06be3bb785..0000000000 --- a/Kernel/Devices/BXVGADevice.cpp +++ /dev/null @@ -1,290 +0,0 @@ -/* - * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org> - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#include <AK/Checked.h> -#include <AK/Format.h> -#include <AK/Singleton.h> -#include <Kernel/Debug.h> -#include <Kernel/Devices/BXVGADevice.h> -#include <Kernel/IO.h> -#include <Kernel/PCI/Access.h> -#include <Kernel/Process.h> -#include <Kernel/VM/AnonymousVMObject.h> -#include <Kernel/VM/MemoryManager.h> -#include <Kernel/VM/TypedMapping.h> -#include <LibC/errno_numbers.h> -#include <LibC/sys/ioctl_numbers.h> - -namespace Kernel { - -#define MAX_RESOLUTION_WIDTH 4096 -#define MAX_RESOLUTION_HEIGHT 2160 - -#define VBE_DISPI_IOPORT_INDEX 0x01CE -#define VBE_DISPI_IOPORT_DATA 0x01CF - -#define VBE_DISPI_INDEX_ID 0x0 -#define VBE_DISPI_INDEX_XRES 0x1 -#define VBE_DISPI_INDEX_YRES 0x2 -#define VBE_DISPI_INDEX_BPP 0x3 -#define VBE_DISPI_INDEX_ENABLE 0x4 -#define VBE_DISPI_INDEX_BANK 0x5 -#define VBE_DISPI_INDEX_VIRT_WIDTH 0x6 -#define VBE_DISPI_INDEX_VIRT_HEIGHT 0x7 -#define VBE_DISPI_INDEX_X_OFFSET 0x8 -#define VBE_DISPI_INDEX_Y_OFFSET 0x9 -#define VBE_DISPI_DISABLED 0x00 -#define VBE_DISPI_ENABLED 0x01 -#define VBE_DISPI_LFB_ENABLED 0x40 - -static AK::Singleton<BXVGADevice> s_the; - -UNMAP_AFTER_INIT void BXVGADevice::initialize() -{ - s_the.ensure_instance(); -} - -BXVGADevice& BXVGADevice::the() -{ - return *s_the; -} - -UNMAP_AFTER_INIT BXVGADevice::BXVGADevice() - : BlockDevice(29, 0) -{ - m_framebuffer_address = PhysicalAddress(find_framebuffer_address()); - m_mmio_registers = find_mmio_region(); - m_vga_compatible = is_vga_compatible(); - - set_register(VBE_DISPI_INDEX_ID, 0xB0C0); - dmesgln("BXVGA: ID {}", get_register(VBE_DISPI_INDEX_ID)); - set_safe_resolution(); -} - -void BXVGADevice::set_safe_resolution() -{ - m_framebuffer_width = 1024; - m_framebuffer_height = 768; - m_framebuffer_pitch = m_framebuffer_width * sizeof(u32); - set_resolution(m_framebuffer_width, m_framebuffer_height); -} - -void BXVGADevice::set_register(u16 index, u16 data) -{ - if (m_vga_compatible) { - IO::out16(VBE_DISPI_IOPORT_INDEX, index); - IO::out16(VBE_DISPI_IOPORT_DATA, data); - return; - } - auto reg = map_typed_writable<u16>(m_mmio_registers.offset(index * 2)); - *(reg.ptr()) = data; -} - -u16 BXVGADevice::get_register(u16 index) -{ - if (m_vga_compatible) { - IO::out16(VBE_DISPI_IOPORT_INDEX, index); - return IO::in16(VBE_DISPI_IOPORT_DATA); - } - auto reg = map_typed_writable<u16>(m_mmio_registers.offset(index * 2)); - return *(reg.ptr()); -} - -void BXVGADevice::revert_resolution() -{ - set_resolution_registers(m_framebuffer_width, m_framebuffer_height); - VERIFY(validate_setup_resolution(m_framebuffer_width, m_framebuffer_height)); -} - -void BXVGADevice::set_resolution_registers(size_t width, size_t height) -{ - dbgln_if(BXVGA_DEBUG, "BXVGADevice resolution registers set to - {}x{}", width, height); - set_register(VBE_DISPI_INDEX_ENABLE, VBE_DISPI_DISABLED); - set_register(VBE_DISPI_INDEX_XRES, (u16)width); - set_register(VBE_DISPI_INDEX_YRES, (u16)height); - set_register(VBE_DISPI_INDEX_VIRT_WIDTH, (u16)width); - set_register(VBE_DISPI_INDEX_VIRT_HEIGHT, (u16)height * 2); - set_register(VBE_DISPI_INDEX_BPP, 32); - set_register(VBE_DISPI_INDEX_ENABLE, VBE_DISPI_ENABLED | VBE_DISPI_LFB_ENABLED); - set_register(VBE_DISPI_INDEX_BANK, 0); -} - -bool BXVGADevice::test_resolution(size_t width, size_t height) -{ - dbgln_if(BXVGA_DEBUG, "BXVGADevice resolution test - {}x{}", width, height); - set_resolution_registers(width, height); - bool resolution_changed = validate_setup_resolution(width, height); - revert_resolution(); - return resolution_changed; -} -bool BXVGADevice::set_resolution(size_t width, size_t height) -{ - if (Checked<size_t>::multiplication_would_overflow(width, height, sizeof(u32))) - return false; - - if (!test_resolution(width, height)) - return false; - - set_resolution_registers(width, height); - dbgln("BXVGADevice resolution set to {}x{} (pitch={})", width, height, m_framebuffer_pitch); - - m_framebuffer_width = width; - m_framebuffer_height = height; - m_framebuffer_pitch = width * sizeof(u32); - return true; -} - -bool BXVGADevice::validate_setup_resolution(size_t width, size_t height) -{ - if ((u16)width != get_register(VBE_DISPI_INDEX_XRES) || (u16)height != get_register(VBE_DISPI_INDEX_YRES)) { - return false; - } - return true; -} - -void BXVGADevice::set_y_offset(size_t y_offset) -{ - VERIFY(y_offset == 0 || y_offset == m_framebuffer_height); - m_y_offset = y_offset; - set_register(VBE_DISPI_INDEX_Y_OFFSET, (u16)y_offset); -} - -UNMAP_AFTER_INIT u32 BXVGADevice::find_framebuffer_address() -{ - // NOTE: The QEMU card has the same PCI ID as the Bochs one. - static const PCI::ID bochs_vga_id = { 0x1234, 0x1111 }; - static const PCI::ID virtualbox_vga_id = { 0x80ee, 0xbeef }; - u32 framebuffer_address = 0; - PCI::enumerate([&framebuffer_address](const PCI::Address& address, PCI::ID id) { - if (id == bochs_vga_id || id == virtualbox_vga_id) { - framebuffer_address = PCI::get_BAR0(address) & 0xfffffff0; - dbgln("BXVGA: framebuffer @ {}", PhysicalAddress(framebuffer_address)); - } - }); - return framebuffer_address; -} - -UNMAP_AFTER_INIT PhysicalAddress BXVGADevice::find_mmio_region() -{ - // NOTE: The QEMU card has the same PCI ID as the Bochs one. - static const PCI::ID bochs_vga_id = { 0x1234, 0x1111 }; - static const PCI::ID virtualbox_vga_id = { 0x80ee, 0xbeef }; - u32 mmio_region = 0; - PCI::enumerate([&mmio_region](const PCI::Address& address, PCI::ID id) { - if (id == bochs_vga_id || id == virtualbox_vga_id) { - mmio_region = PCI::get_BAR1(address) & 0xfffffff0; - dmesgln("BXVGA: mmio region @ {}", PhysicalAddress(mmio_region)); - } - }); - return PhysicalAddress(mmio_region); -} - -UNMAP_AFTER_INIT bool BXVGADevice::is_vga_compatible() -{ - // NOTE: The QEMU card has the same PCI ID as the Bochs one. - static const PCI::ID bochs_vga_id = { 0x1234, 0x1111 }; - static const PCI::ID virtualbox_vga_id = { 0x80ee, 0xbeef }; - bool vga_compatible = true; - PCI::enumerate([&vga_compatible](const PCI::Address& address, PCI::ID id) { - if (id == bochs_vga_id || id == virtualbox_vga_id) { - if (PCI::get_subclass(address) != 0) - vga_compatible = false; - } - }); - return vga_compatible; -} - -KResultOr<Region*> BXVGADevice::mmap(Process& process, FileDescription&, const Range& range, u64 offset, int prot, bool shared) -{ - REQUIRE_PROMISE(video); - if (!shared) - return ENODEV; - if (offset != 0) - return ENXIO; - if (range.size() != page_round_up(framebuffer_size_in_bytes())) - return EOVERFLOW; - - auto vmobject = AnonymousVMObject::create_for_physical_range(m_framebuffer_address, framebuffer_size_in_bytes()); - if (!vmobject) - return ENOMEM; - return process.space().allocate_region_with_vmobject( - range, - vmobject.release_nonnull(), - 0, - "BXVGA Framebuffer", - prot, - shared); -} - -String BXVGADevice::device_name() const -{ - return String::formatted("fb{}", minor()); -} - -int BXVGADevice::ioctl(FileDescription&, unsigned request, FlatPtr arg) -{ - REQUIRE_PROMISE(video); - switch (request) { - case FB_IOCTL_GET_SIZE_IN_BYTES: { - auto* out = (size_t*)arg; - size_t value = framebuffer_size_in_bytes(); - if (!copy_to_user(out, &value)) - return -EFAULT; - return 0; - } - case FB_IOCTL_GET_BUFFER: { - auto* index = (int*)arg; - int value = m_y_offset == 0 ? 0 : 1; - if (!copy_to_user(index, &value)) - return -EFAULT; - return 0; - } - case FB_IOCTL_SET_BUFFER: { - if (arg != 0 && arg != 1) - return -EINVAL; - set_y_offset(arg == 0 ? 0 : m_framebuffer_height); - return 0; - } - case FB_IOCTL_GET_RESOLUTION: { - auto* user_resolution = (FBResolution*)arg; - FBResolution resolution; - resolution.pitch = m_framebuffer_pitch; - resolution.width = m_framebuffer_width; - resolution.height = m_framebuffer_height; - if (!copy_to_user(user_resolution, &resolution)) - return -EFAULT; - return 0; - } - case FB_IOCTL_SET_RESOLUTION: { - auto* user_resolution = (FBResolution*)arg; - FBResolution resolution; - if (!copy_from_user(&resolution, user_resolution)) - return -EFAULT; - if (resolution.width > MAX_RESOLUTION_WIDTH || resolution.height > MAX_RESOLUTION_HEIGHT) - return -EINVAL; - if (!set_resolution(resolution.width, resolution.height)) { - dbgln_if(BXVGA_DEBUG, "Reverting resolution: [{}x{}]", m_framebuffer_width, m_framebuffer_height); - resolution.pitch = m_framebuffer_pitch; - resolution.width = m_framebuffer_width; - resolution.height = m_framebuffer_height; - if (!copy_to_user(user_resolution, &resolution)) - return -EFAULT; - return -EINVAL; - } - dbgln_if(BXVGA_DEBUG, "New resolution: [{}x{}]", m_framebuffer_width, m_framebuffer_height); - resolution.pitch = m_framebuffer_pitch; - resolution.width = m_framebuffer_width; - resolution.height = m_framebuffer_height; - if (!copy_to_user(user_resolution, &resolution)) - return -EFAULT; - return 0; - } - default: - return -EINVAL; - }; -} - -} diff --git a/Kernel/Devices/BXVGADevice.h b/Kernel/Devices/BXVGADevice.h deleted file mode 100644 index b1692dc9f7..0000000000 --- a/Kernel/Devices/BXVGADevice.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org> - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#pragma once - -#include <AK/String.h> -#include <AK/Types.h> -#include <Kernel/Devices/BlockDevice.h> -#include <Kernel/PhysicalAddress.h> - -namespace Kernel { - -class BXVGADevice final : public BlockDevice { - AK_MAKE_ETERNAL -public: - static void initialize(); - static BXVGADevice& the(); - - BXVGADevice(); - - virtual int ioctl(FileDescription&, unsigned request, FlatPtr arg) override; - virtual KResultOr<Region*> mmap(Process&, FileDescription&, const Range&, u64 offset, int prot, bool shared) override; - - // ^Device - virtual mode_t required_mode() const override { return 0660; } - virtual String device_name() const override; - -private: - virtual const char* class_name() const override { return "BXVGA"; } - virtual bool can_read(const FileDescription&, size_t) const override { return true; } - virtual bool can_write(const FileDescription&, size_t) const override { return true; } - virtual void start_request(AsyncBlockDeviceRequest& request) override { request.complete(AsyncDeviceRequest::Failure); } - virtual KResultOr<size_t> read(FileDescription&, u64, UserOrKernelBuffer&, size_t) override { return EINVAL; } - virtual KResultOr<size_t> write(FileDescription&, u64, const UserOrKernelBuffer&, size_t) override { return EINVAL; } - - PhysicalAddress find_mmio_region(); - bool is_vga_compatible(); - - void set_safe_resolution(); - - void set_register(u16 index, u16 value); - u16 get_register(u16 index); - bool validate_setup_resolution(size_t width, size_t height); - u32 find_framebuffer_address(); - void revert_resolution(); - bool test_resolution(size_t width, size_t height); - size_t framebuffer_size_in_bytes() const { return m_framebuffer_pitch * m_framebuffer_height * 2; } - bool set_resolution(size_t width, size_t height); - void set_resolution_registers(size_t width, size_t height); - void set_y_offset(size_t); - - PhysicalAddress m_framebuffer_address; - PhysicalAddress m_mmio_registers; - bool m_vga_compatible { true }; - size_t m_framebuffer_pitch { 0 }; - size_t m_framebuffer_width { 0 }; - size_t m_framebuffer_height { 0 }; - size_t m_y_offset { 0 }; -}; - -} diff --git a/Kernel/Graphics/Bochs.h b/Kernel/Graphics/Bochs.h new file mode 100644 index 0000000000..19b9d08a4b --- /dev/null +++ b/Kernel/Graphics/Bochs.h @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2021, Liav A. <liavalb@hotmail.co.il> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#define MAX_RESOLUTION_WIDTH 4096 +#define MAX_RESOLUTION_HEIGHT 2160 + +#define VBE_DISPI_IOPORT_INDEX 0x01CE +#define VBE_DISPI_IOPORT_DATA 0x01CF + +#define VBE_DISPI_INDEX_ID 0x0 +#define VBE_DISPI_INDEX_XRES 0x1 +#define VBE_DISPI_INDEX_YRES 0x2 +#define VBE_DISPI_INDEX_BPP 0x3 +#define VBE_DISPI_INDEX_ENABLE 0x4 +#define VBE_DISPI_INDEX_BANK 0x5 +#define VBE_DISPI_INDEX_VIRT_WIDTH 0x6 +#define VBE_DISPI_INDEX_VIRT_HEIGHT 0x7 +#define VBE_DISPI_INDEX_X_OFFSET 0x8 +#define VBE_DISPI_INDEX_Y_OFFSET 0x9 +#define VBE_DISPI_DISABLED 0x00 +#define VBE_DISPI_ENABLED 0x01 +#define VBE_DISPI_LFB_ENABLED 0x40 diff --git a/Kernel/Graphics/BochsFramebufferDevice.cpp b/Kernel/Graphics/BochsFramebufferDevice.cpp new file mode 100644 index 0000000000..15af62d532 --- /dev/null +++ b/Kernel/Graphics/BochsFramebufferDevice.cpp @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2021, Liav A. <liavalb@hotmail.co.il> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include <AK/Checked.h> +#include <AK/Singleton.h> +#include <Kernel/Debug.h> +#include <Kernel/Graphics/Bochs.h> +#include <Kernel/Graphics/BochsFramebufferDevice.h> +#include <Kernel/IO.h> +#include <Kernel/PCI/Access.h> +#include <Kernel/Process.h> +#include <LibC/errno_numbers.h> +#include <LibC/sys/ioctl_numbers.h> + +namespace Kernel { + +UNMAP_AFTER_INIT NonnullRefPtr<BochsFramebufferDevice> BochsFramebufferDevice::create(const BochsGraphicsAdapter& adapter, PhysicalAddress framebuffer_address, size_t pitch, size_t width, size_t height) +{ + return adopt_ref(*new BochsFramebufferDevice(adapter, framebuffer_address, pitch, width, height)); +} + +UNMAP_AFTER_INIT BochsFramebufferDevice::BochsFramebufferDevice(const BochsGraphicsAdapter& adapter, PhysicalAddress framebuffer_address, size_t pitch, size_t width, size_t height) + : FramebufferDevice(framebuffer_address, pitch, width, height) + , m_bochs_adapter(adapter) +{ + m_bochs_adapter->set_safe_resolution(); + m_framebuffer_width = 1024; + m_framebuffer_height = 768; + m_framebuffer_pitch = m_framebuffer_width * sizeof(u32); +} + +void BochsFramebufferDevice::set_y_offset(size_t y_offset) +{ + VERIFY(y_offset == 0 || y_offset == m_framebuffer_height); + m_y_offset = y_offset; + m_bochs_adapter->set_y_offset(y_offset); +} + +int BochsFramebufferDevice::ioctl(FileDescription&, unsigned request, FlatPtr arg) +{ + REQUIRE_PROMISE(video); + switch (request) { + case FB_IOCTL_GET_SIZE_IN_BYTES: { + auto* out = (size_t*)arg; + size_t value = framebuffer_size_in_bytes(); + if (!copy_to_user(out, &value)) + return -EFAULT; + return 0; + } + case FB_IOCTL_GET_BUFFER: { + auto* index = (int*)arg; + int value = m_y_offset == 0 ? 0 : 1; + if (!copy_to_user(index, &value)) + return -EFAULT; + return 0; + } + case FB_IOCTL_SET_BUFFER: { + if (arg != 0 && arg != 1) + return -EINVAL; + set_y_offset(arg == 0 ? 0 : m_framebuffer_height); + return 0; + } + case FB_IOCTL_GET_RESOLUTION: { + auto* user_resolution = (FBResolution*)arg; + FBResolution resolution; + resolution.pitch = m_framebuffer_pitch; + resolution.width = m_framebuffer_width; + resolution.height = m_framebuffer_height; + if (!copy_to_user(user_resolution, &resolution)) + return -EFAULT; + return 0; + } + case FB_IOCTL_SET_RESOLUTION: { + auto* user_resolution = (FBResolution*)arg; + FBResolution resolution; + if (!copy_from_user(&resolution, user_resolution)) + return -EFAULT; + if (resolution.width > MAX_RESOLUTION_WIDTH || resolution.height > MAX_RESOLUTION_HEIGHT) + return -EINVAL; + + if (!m_bochs_adapter->set_resolution(resolution.width, resolution.height)) { + m_framebuffer_pitch = m_framebuffer_width * sizeof(u32); + dbgln_if(BXVGA_DEBUG, "Reverting resolution: [{}x{}]", m_framebuffer_width, m_framebuffer_height); + // Note: We try to revert everything back, and if it doesn't work, just assert. + if (!m_bochs_adapter->set_resolution(m_framebuffer_width, m_framebuffer_height)) { + VERIFY_NOT_REACHED(); + } + resolution.pitch = m_framebuffer_pitch; + resolution.width = m_framebuffer_width; + resolution.height = m_framebuffer_height; + if (!copy_to_user(user_resolution, &resolution)) + return -EFAULT; + return -EINVAL; + } + m_framebuffer_width = resolution.width; + m_framebuffer_height = resolution.height; + m_framebuffer_pitch = m_framebuffer_width * sizeof(u32); + + dbgln_if(BXVGA_DEBUG, "New resolution: [{}x{}]", m_framebuffer_width, m_framebuffer_height); + resolution.pitch = m_framebuffer_pitch; + resolution.width = m_framebuffer_width; + resolution.height = m_framebuffer_height; + if (!copy_to_user(user_resolution, &resolution)) + return -EFAULT; + return 0; + } + default: + return -EINVAL; + }; +} +} diff --git a/Kernel/Graphics/BochsFramebufferDevice.h b/Kernel/Graphics/BochsFramebufferDevice.h new file mode 100644 index 0000000000..5133c3320f --- /dev/null +++ b/Kernel/Graphics/BochsFramebufferDevice.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2021, Liav A. <liavalb@hotmail.co.il> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include <AK/String.h> +#include <AK/Types.h> +#include <Kernel/Graphics/BochsGraphicsAdapter.h> +#include <Kernel/Graphics/FramebufferDevice.h> +#include <Kernel/PhysicalAddress.h> + +namespace Kernel { + +class BochsFramebufferDevice final : public FramebufferDevice { + AK_MAKE_ETERNAL + friend class BochsGraphicsAdapter; + +public: + static NonnullRefPtr<BochsFramebufferDevice> create(const BochsGraphicsAdapter&, PhysicalAddress, size_t, size_t, size_t); + + virtual size_t framebuffer_size_in_bytes() const override { return m_framebuffer_pitch * m_framebuffer_height * 2; } + + virtual ~BochsFramebufferDevice() = default; + +private: + virtual int ioctl(FileDescription&, unsigned request, FlatPtr arg) override; + + BochsFramebufferDevice(const BochsGraphicsAdapter&, PhysicalAddress, size_t, size_t, size_t); + virtual const char* class_name() const override { return "BXVGA"; } + + void set_y_offset(size_t); + + size_t m_y_offset { 0 }; + + NonnullRefPtr<BochsGraphicsAdapter> m_bochs_adapter; +}; + +} diff --git a/Kernel/Graphics/BochsGraphicsAdapter.cpp b/Kernel/Graphics/BochsGraphicsAdapter.cpp new file mode 100644 index 0000000000..d6f42b1662 --- /dev/null +++ b/Kernel/Graphics/BochsGraphicsAdapter.cpp @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2021, Liav A. <liavalb@hotmail.co.il> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include <AK/Atomic.h> +#include <AK/Checked.h> +#include <AK/Singleton.h> +#include <Kernel/Debug.h> +#include <Kernel/Graphics/Bochs.h> +#include <Kernel/Graphics/BochsFramebufferDevice.h> +#include <Kernel/Graphics/BochsGraphicsAdapter.h> +#include <Kernel/IO.h> +#include <Kernel/PCI/Access.h> +#include <Kernel/Process.h> +#include <Kernel/VM/AnonymousVMObject.h> +#include <Kernel/VM/MemoryManager.h> +#include <Kernel/VM/TypedMapping.h> +#include <LibC/errno_numbers.h> +#include <LibC/sys/ioctl_numbers.h> + +namespace Kernel { + +struct [[gnu::packed]] DISPIInterface { + u16 index_id; + u16 xres; + u16 yres; + u16 bpp; + u16 enable; + u16 bank; + u16 virt_width; + u16 virt_height; + u16 x_offset; + u16 y_offset; +}; + +struct [[gnu::packed]] BochsDisplayMMIORegisters { + u8 edid_data[0x400]; + u16 vga_ioports[0x10]; + u8 reserved[0xE0]; + DISPIInterface bochs_regs; +}; + +UNMAP_AFTER_INIT NonnullRefPtr<BochsGraphicsAdapter> BochsGraphicsAdapter::initialize(PCI::Address address) +{ + return adopt_ref(*new BochsGraphicsAdapter(address)); +} + +UNMAP_AFTER_INIT BochsGraphicsAdapter::BochsGraphicsAdapter(PCI::Address pci_address) + : PCI::DeviceController(pci_address) + , m_mmio_registers(PCI::get_BAR2(pci_address) & 0xfffffff0) +{ + set_safe_resolution(); +} + +UNMAP_AFTER_INIT void BochsGraphicsAdapter::initialize_framebuffer_devices() +{ + // FIXME: Find a better way to determine default resolution... + m_framebuffer = BochsFramebufferDevice::create(*this, PhysicalAddress(PCI::get_BAR0(pci_address()) & 0xfffffff0), 1024 * 4, 1024, 768); +} + +GraphicsDevice::Type BochsGraphicsAdapter::type() const +{ + if (PCI::get_class(pci_address()) == 0x3 && PCI::get_subclass(pci_address()) == 0x0) + return Type::VGACompatible; + return Type::Bochs; +} + +void BochsGraphicsAdapter::set_safe_resolution() +{ + set_resolution(1024, 768); +} + +void BochsGraphicsAdapter::set_resolution_registers(size_t width, size_t height) +{ + dbgln_if(BXVGA_DEBUG, "BochsGraphicsAdapter resolution registers set to - {}x{}", width, height); + auto registers = map_typed_writable<volatile BochsDisplayMMIORegisters>(m_mmio_registers); + registers->bochs_regs.enable = VBE_DISPI_DISABLED; + full_memory_barrier(); + registers->bochs_regs.xres = width; + registers->bochs_regs.yres = height; + registers->bochs_regs.virt_width = width; + registers->bochs_regs.virt_height = height * 2; + registers->bochs_regs.bpp = 32; + full_memory_barrier(); + registers->bochs_regs.enable = VBE_DISPI_ENABLED | VBE_DISPI_LFB_ENABLED; + full_memory_barrier(); + registers->bochs_regs.bank = 0; +} + +bool BochsGraphicsAdapter::try_to_set_resolution(size_t width, size_t height) +{ + dbgln_if(BXVGA_DEBUG, "BochsGraphicsAdapter resolution test - {}x{}", width, height); + set_resolution_registers(width, height); + return validate_setup_resolution(width, height); +} + +bool BochsGraphicsAdapter::set_resolution(size_t width, size_t height) +{ + if (Checked<size_t>::multiplication_would_overflow(width, height, sizeof(u32))) + return false; + + if (!try_to_set_resolution(width, height)) + return false; + + dbgln("BochsGraphicsAdapter: resolution set to {}x{}", width, height); + return true; +} + +bool BochsGraphicsAdapter::validate_setup_resolution(size_t width, size_t height) +{ + auto registers = map_typed_writable<volatile BochsDisplayMMIORegisters>(m_mmio_registers); + if ((u16)width != registers->bochs_regs.xres || (u16)height != registers->bochs_regs.yres) { + return false; + } + return true; +} + +void BochsGraphicsAdapter::set_y_offset(size_t y_offset) +{ + auto registers = map_typed_writable<volatile BochsDisplayMMIORegisters>(m_mmio_registers); + registers->bochs_regs.y_offset = y_offset; +} + +} diff --git a/Kernel/Graphics/BochsGraphicsAdapter.h b/Kernel/Graphics/BochsGraphicsAdapter.h new file mode 100644 index 0000000000..e2c2b1cdd5 --- /dev/null +++ b/Kernel/Graphics/BochsGraphicsAdapter.h @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2021, Liav A. <liavalb@hotmail.co.il> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include <AK/String.h> +#include <AK/Types.h> +#include <Kernel/Graphics/GraphicsDevice.h> +#include <Kernel/PCI/DeviceController.h> +#include <Kernel/PhysicalAddress.h> + +namespace Kernel { + +class BochsFramebufferDevice; +class GraphicsManagement; +class BochsGraphicsAdapter final : public GraphicsDevice + , public PCI::DeviceController { + AK_MAKE_ETERNAL + friend class BochsFramebufferDevice; + friend class GraphicsManagement; + +public: + static NonnullRefPtr<BochsGraphicsAdapter> initialize(PCI::Address); + virtual ~BochsGraphicsAdapter() = default; + +private: + // ^GraphicsDevice + virtual void initialize_framebuffer_devices() override; + virtual Type type() const override; + + explicit BochsGraphicsAdapter(PCI::Address); + + void set_safe_resolution(); + + bool validate_setup_resolution(size_t width, size_t height); + u32 find_framebuffer_address(); + bool try_to_set_resolution(size_t width, size_t height); + bool set_resolution(size_t width, size_t height); + void set_resolution_registers(size_t width, size_t height); + void set_y_offset(size_t); + + PhysicalAddress m_mmio_registers; + RefPtr<BochsFramebufferDevice> m_framebuffer; +}; + +} diff --git a/Kernel/Devices/MBVGADevice.cpp b/Kernel/Graphics/FramebufferDevice.cpp index bfefe387d8..c6d45774cf 100644 --- a/Kernel/Devices/MBVGADevice.cpp +++ b/Kernel/Graphics/FramebufferDevice.cpp @@ -1,37 +1,24 @@ /* - * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org> + * Copyright (c) 2021, Liav A. <liavalb@hotmail.co.il> * * SPDX-License-Identifier: BSD-2-Clause */ -#include <Kernel/Devices/MBVGADevice.h> +#include <AK/Checked.h> +#include <AK/Singleton.h> +#include <Kernel/Debug.h> +#include <Kernel/Graphics/FramebufferDevice.h> +#include <Kernel/Graphics/GraphicsManagement.h> #include <Kernel/Process.h> #include <Kernel/VM/AnonymousVMObject.h> #include <Kernel/VM/MemoryManager.h> +#include <Kernel/VM/TypedMapping.h> #include <LibC/errno_numbers.h> #include <LibC/sys/ioctl_numbers.h> namespace Kernel { -static MBVGADevice* s_the; - -MBVGADevice& MBVGADevice::the() -{ - return *s_the; -} - -UNMAP_AFTER_INIT MBVGADevice::MBVGADevice(PhysicalAddress addr, size_t pitch, size_t width, size_t height) - : BlockDevice(29, 0) - , m_framebuffer_address(addr) - , m_framebuffer_pitch(pitch) - , m_framebuffer_width(width) - , m_framebuffer_height(height) -{ - dbgln("MBVGADevice address={}, pitch={}, width={}, height={}", addr, pitch, width, height); - s_the = this; -} - -KResultOr<Region*> MBVGADevice::mmap(Process& process, FileDescription&, const Range& range, u64 offset, int prot, bool shared) +KResultOr<Region*> FramebufferDevice::mmap(Process& process, FileDescription&, const Range& range, u64 offset, int prot, bool shared) { REQUIRE_PROMISE(video); if (!shared) @@ -48,12 +35,32 @@ KResultOr<Region*> MBVGADevice::mmap(Process& process, FileDescription&, const R range, vmobject.release_nonnull(), 0, - "MBVGA Framebuffer", + "Framebuffer", prot, shared); } -int MBVGADevice::ioctl(FileDescription&, unsigned request, FlatPtr arg) +String FramebufferDevice::device_name() const +{ + return String::formatted("fb{}", minor()); +} + +UNMAP_AFTER_INIT FramebufferDevice::FramebufferDevice(PhysicalAddress addr, size_t pitch, size_t width, size_t height) + : BlockDevice(29, GraphicsManagement::the().current_minor_number()) + , m_framebuffer_address(addr) + , m_framebuffer_pitch(pitch) + , m_framebuffer_width(width) + , m_framebuffer_height(height) +{ + dbgln("Framebuffer {}: address={}, pitch={}, width={}, height={}", minor(), addr, pitch, width, height); +} + +bool FramebufferDevice::set_resolution(size_t, size_t, size_t) +{ + VERIFY_NOT_REACHED(); +} + +int FramebufferDevice::ioctl(FileDescription&, unsigned request, FlatPtr arg) { REQUIRE_PROMISE(video); switch (request) { @@ -65,11 +72,7 @@ int MBVGADevice::ioctl(FileDescription&, unsigned request, FlatPtr arg) return 0; } case FB_IOCTL_GET_BUFFER: { - auto* index = (int*)arg; - int value = 0; - if (!copy_to_user(index, &value)) - return -EFAULT; - return 0; + return -ENOTIMPL; } case FB_IOCTL_GET_RESOLUTION: { auto* user_resolution = (FBResolution*)arg; @@ -96,9 +99,4 @@ int MBVGADevice::ioctl(FileDescription&, unsigned request, FlatPtr arg) }; } -String MBVGADevice::device_name() const -{ - return String::formatted("fb{}", minor()); -} - } diff --git a/Kernel/Devices/MBVGADevice.h b/Kernel/Graphics/FramebufferDevice.h index db473c5443..104fc5739d 100644 --- a/Kernel/Devices/MBVGADevice.h +++ b/Kernel/Graphics/FramebufferDevice.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org> + * Copyright (c) 2021, Liav A. <liavalb@hotmail.co.il> * * SPDX-License-Identifier: BSD-2-Clause */ @@ -9,17 +9,14 @@ #include <AK/String.h> #include <AK/Types.h> #include <Kernel/Devices/BlockDevice.h> +#include <Kernel/Graphics/GraphicsDevice.h> #include <Kernel/PhysicalAddress.h> namespace Kernel { -class MBVGADevice final : public BlockDevice { +class FramebufferDevice : public BlockDevice { AK_MAKE_ETERNAL public: - static MBVGADevice& the(); - - MBVGADevice(PhysicalAddress addr, size_t pitch, size_t width, size_t height); - virtual int ioctl(FileDescription&, unsigned request, FlatPtr arg) override; virtual KResultOr<Region*> mmap(Process&, FileDescription&, const Range&, u64 offset, int prot, bool shared) override; @@ -27,16 +24,22 @@ public: virtual mode_t required_mode() const override { return 0660; } virtual String device_name() const override; -private: - virtual const char* class_name() const override { return "MBVGA"; } - virtual bool can_read(const FileDescription&, size_t) const override { return true; } - virtual bool can_write(const FileDescription&, size_t) const override { return true; } + virtual size_t framebuffer_size_in_bytes() const { return m_framebuffer_pitch * m_framebuffer_height; } + + virtual ~FramebufferDevice() {}; + +protected: + virtual bool set_resolution(size_t framebuffer_width, size_t framebuffer_height, size_t framebuffer_pitch); + + FramebufferDevice(PhysicalAddress, size_t, size_t, size_t); + + virtual bool can_read(const FileDescription&, size_t) const override final { return true; } + virtual bool can_write(const FileDescription&, size_t) const override final { return true; } + virtual void start_request(AsyncBlockDeviceRequest& request) override final { request.complete(AsyncDeviceRequest::Failure); } virtual KResultOr<size_t> read(FileDescription&, u64, UserOrKernelBuffer&, size_t) override { return -EINVAL; } virtual KResultOr<size_t> write(FileDescription&, u64, const UserOrKernelBuffer&, size_t) override { return -EINVAL; } - virtual void start_request(AsyncBlockDeviceRequest& request) override { request.complete(AsyncDeviceRequest::Failure); } - - size_t framebuffer_size_in_bytes() const { return m_framebuffer_pitch * m_framebuffer_height; } +protected: PhysicalAddress m_framebuffer_address; size_t m_framebuffer_pitch { 0 }; size_t m_framebuffer_width { 0 }; diff --git a/Kernel/Graphics/GraphicsDevice.h b/Kernel/Graphics/GraphicsDevice.h new file mode 100644 index 0000000000..f4d3ae7e29 --- /dev/null +++ b/Kernel/Graphics/GraphicsDevice.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2021, Liav A. <liavalb@hotmail.co.il> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include <AK/String.h> +#include <AK/Types.h> +#include <Kernel/Devices/BlockDevice.h> +#include <Kernel/Graphics/FramebufferDevice.h> +#include <Kernel/PhysicalAddress.h> + +namespace Kernel { +class FramebufferDevice; +class GraphicsDevice : public RefCounted<GraphicsDevice> { +public: + enum class Type { + VGACompatible, + Bochs, + SVGA, + Raw + }; + virtual ~GraphicsDevice() = default; + virtual void initialize_framebuffer_devices() = 0; + virtual Type type() const = 0; + +protected: + GraphicsDevice() = default; +}; + +} diff --git a/Kernel/Graphics/GraphicsManagement.cpp b/Kernel/Graphics/GraphicsManagement.cpp new file mode 100644 index 0000000000..4fbef68629 --- /dev/null +++ b/Kernel/Graphics/GraphicsManagement.cpp @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2021, Liav A. <liavalb@hotmail.co.il> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include <AK/Checked.h> +#include <AK/Singleton.h> +#include <Kernel/CommandLine.h> +#include <Kernel/Debug.h> +#include <Kernel/Graphics/BochsGraphicsAdapter.h> +#include <Kernel/Graphics/GraphicsManagement.h> +#include <Kernel/Graphics/VGACompatibleAdapter.h> +#include <Kernel/Multiboot.h> + +namespace Kernel { + +static AK::Singleton<GraphicsManagement> s_the; + +GraphicsManagement& GraphicsManagement::the() +{ + return *s_the; +} + +bool GraphicsManagement::is_initialized() +{ + return s_the.is_initialized(); +} + +UNMAP_AFTER_INIT GraphicsManagement::GraphicsManagement() + : m_textmode_enabled(kernel_command_line().is_text_mode()) +{ +} + +UNMAP_AFTER_INIT RefPtr<GraphicsDevice> GraphicsManagement::determine_graphics_device(PCI::Address address, PCI::ID id) const +{ + if ((id.vendor_id == 0x1234 && id.device_id == 0x1111) || (id.vendor_id == 0x80ee && id.device_id == 0xbeef)) { + return BochsGraphicsAdapter::initialize(address); + } + if (PCI::get_class(address) == 0x3 && PCI::get_subclass(address) == 0x0) { + VERIFY(multiboot_info_ptr->framebuffer_type == MULTIBOOT_FRAMEBUFFER_TYPE_RGB || multiboot_info_ptr->framebuffer_type == MULTIBOOT_FRAMEBUFFER_TYPE_EGA_TEXT); + return VGACompatibleAdapter::initialize_with_preset_resolution(address, + PhysicalAddress((u32)(multiboot_info_ptr->framebuffer_addr)), + multiboot_info_ptr->framebuffer_pitch, + multiboot_info_ptr->framebuffer_width, + multiboot_info_ptr->framebuffer_height); + } + return {}; +} + +UNMAP_AFTER_INIT bool GraphicsManagement::initialize() +{ + if (kernel_command_line().is_text_mode()) { + dbgln("Text mode enabled"); + return false; + } + + PCI::enumerate([&](const PCI::Address& address, PCI::ID id) { + auto adapter = determine_graphics_device(address, id); + if (!adapter) + return; + adapter->initialize_framebuffer_devices(); + m_graphics_devices.append(adapter.release_nonnull()); + }); + return true; +} + +} diff --git a/Kernel/Graphics/GraphicsManagement.h b/Kernel/Graphics/GraphicsManagement.h new file mode 100644 index 0000000000..bcf0cded39 --- /dev/null +++ b/Kernel/Graphics/GraphicsManagement.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2021, Liav A. <liavalb@hotmail.co.il> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include <AK/NonnullRefPtr.h> +#include <AK/NonnullRefPtrVector.h> +#include <AK/Types.h> +#include <Kernel/Graphics/GraphicsDevice.h> +#include <Kernel/PCI/Definitions.h> + +namespace Kernel { + +class GraphicsManagement { + AK_MAKE_ETERNAL; + +public: + static GraphicsManagement& the(); + static bool is_initialized(); + bool initialize(); + + unsigned current_minor_number() { return m_current_minor_number++; }; + GraphicsManagement(); + + bool is_text_mode_enabled() const { return m_textmode_enabled; } + +private: + RefPtr<GraphicsDevice> determine_graphics_device(PCI::Address address, PCI::ID id) const; + + NonnullRefPtrVector<GraphicsDevice> m_graphics_devices; + unsigned m_current_minor_number { 0 }; + bool m_textmode_enabled; +}; + +} diff --git a/Kernel/Graphics/RawFramebufferDevice.cpp b/Kernel/Graphics/RawFramebufferDevice.cpp new file mode 100644 index 0000000000..f36a5cfa27 --- /dev/null +++ b/Kernel/Graphics/RawFramebufferDevice.cpp @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2021, Liav A. <liavalb@hotmail.co.il> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include <Kernel/Graphics/RawFramebufferDevice.h> + +namespace Kernel { + +UNMAP_AFTER_INIT NonnullRefPtr<RawFramebufferDevice> RawFramebufferDevice::create(const GraphicsDevice&, PhysicalAddress framebuffer_address, size_t pitch, size_t width, size_t height) +{ + return adopt_ref(*new RawFramebufferDevice(framebuffer_address, pitch, width, height)); +} +UNMAP_AFTER_INIT RawFramebufferDevice::RawFramebufferDevice(PhysicalAddress framebuffer_address, size_t pitch, size_t width, size_t height) + : FramebufferDevice(framebuffer_address, pitch, width, height) +{ +} + +} diff --git a/Kernel/Graphics/RawFramebufferDevice.h b/Kernel/Graphics/RawFramebufferDevice.h new file mode 100644 index 0000000000..10ddf44ea8 --- /dev/null +++ b/Kernel/Graphics/RawFramebufferDevice.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2021, Liav A. <liavalb@hotmail.co.il> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include <AK/String.h> +#include <AK/Types.h> +#include <Kernel/Graphics/FramebufferDevice.h> +#include <Kernel/Graphics/GraphicsDevice.h> +#include <Kernel/PhysicalAddress.h> + +namespace Kernel { + +class RawFramebufferDevice : public FramebufferDevice { + AK_MAKE_ETERNAL + friend class GraphicsDevice; + +public: + static NonnullRefPtr<RawFramebufferDevice> create(const GraphicsDevice&, PhysicalAddress, size_t pitch, size_t width, size_t height); + + virtual ~RawFramebufferDevice() {}; + +private: + RawFramebufferDevice(PhysicalAddress, size_t pitch, size_t width, size_t height); + virtual const char* class_name() const override { return "RawFramebuffer"; } +}; + +} diff --git a/Kernel/Graphics/VGACompatibleAdapter.cpp b/Kernel/Graphics/VGACompatibleAdapter.cpp new file mode 100644 index 0000000000..80b2e8b0d4 --- /dev/null +++ b/Kernel/Graphics/VGACompatibleAdapter.cpp @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2021, Liav A. <liavalb@hotmail.co.il> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include <Kernel/Graphics/VGACompatibleAdapter.h> + +namespace Kernel { + +UNMAP_AFTER_INIT NonnullRefPtr<VGACompatibleAdapter> VGACompatibleAdapter::initialize_with_preset_resolution(PCI::Address address, PhysicalAddress m_framebuffer_address, size_t framebuffer_width, size_t framebuffer_height, size_t framebuffer_pitch) +{ + return adopt_ref(*new VGACompatibleAdapter(address, m_framebuffer_address, framebuffer_width, framebuffer_height, framebuffer_pitch)); +} + +UNMAP_AFTER_INIT void VGACompatibleAdapter::initialize_framebuffer_devices() +{ +} + +UNMAP_AFTER_INIT VGACompatibleAdapter::VGACompatibleAdapter(PCI::Address address) + : PCI::DeviceController(address) +{ +} + +UNMAP_AFTER_INIT VGACompatibleAdapter::VGACompatibleAdapter(PCI::Address address, PhysicalAddress framebuffer_address, size_t framebuffer_width, size_t framebuffer_height, size_t framebuffer_pitch) + : PCI::DeviceController(address) +{ + m_framebuffer = RawFramebufferDevice::create(*this, framebuffer_address, framebuffer_width, framebuffer_height, framebuffer_pitch); +} + +} diff --git a/Kernel/Graphics/VGACompatibleAdapter.h b/Kernel/Graphics/VGACompatibleAdapter.h new file mode 100644 index 0000000000..75ed5ee946 --- /dev/null +++ b/Kernel/Graphics/VGACompatibleAdapter.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2021, Liav A. <liavalb@hotmail.co.il> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include <AK/String.h> +#include <AK/Types.h> +#include <Kernel/Graphics/GraphicsDevice.h> +#include <Kernel/Graphics/RawFramebufferDevice.h> +#include <Kernel/PCI/DeviceController.h> +#include <Kernel/PhysicalAddress.h> + +namespace Kernel { + +class VGACompatibleAdapter final : public GraphicsDevice + , public PCI::DeviceController { + AK_MAKE_ETERNAL +public: + static NonnullRefPtr<VGACompatibleAdapter> initialize_with_preset_resolution(PCI::Address, PhysicalAddress, size_t framebuffer_width, size_t framebuffer_height, size_t framebuffer_pitch); + +protected: + explicit VGACompatibleAdapter(PCI::Address); + +private: + VGACompatibleAdapter(PCI::Address, PhysicalAddress, size_t framebuffer_width, size_t framebuffer_height, size_t framebuffer_pitch); + + // ^GraphicsDevice + virtual void initialize_framebuffer_devices() override; + virtual Type type() const override { return Type::VGACompatible; } + +protected: + RefPtr<RawFramebufferDevice> m_framebuffer; +}; + +} diff --git a/Kernel/init.cpp b/Kernel/init.cpp index 1918aa1dc8..e497688b56 100644 --- a/Kernel/init.cpp +++ b/Kernel/init.cpp @@ -12,10 +12,8 @@ #include <Kernel/CMOS.h> #include <Kernel/CommandLine.h> #include <Kernel/DMI.h> -#include <Kernel/Devices/BXVGADevice.h> #include <Kernel/Devices/FullDevice.h> #include <Kernel/Devices/HID/HIDManagement.h> -#include <Kernel/Devices/MBVGADevice.h> #include <Kernel/Devices/MemoryDevice.h> #include <Kernel/Devices/NullDevice.h> #include <Kernel/Devices/RandomDevice.h> @@ -26,6 +24,7 @@ #include <Kernel/Devices/ZeroDevice.h> #include <Kernel/FileSystem/Ext2FileSystem.h> #include <Kernel/FileSystem/VirtualFileSystem.h> +#include <Kernel/Graphics/GraphicsManagement.h> #include <Kernel/Heap/SlabAllocator.h> #include <Kernel/Heap/kmalloc.h> #include <Kernel/Interrupts/APIC.h> @@ -233,30 +232,8 @@ void init_stage2(void*) PCI::initialize(); auto boot_profiling = kernel_command_line().is_boot_profiling_enabled(); - auto is_text_mode = kernel_command_line().is_text_mode(); - if (is_text_mode) { - dbgln("Text mode enabled"); - } else { - bool bxvga_found = false; - PCI::enumerate([&](const PCI::Address&, PCI::ID id) { - if ((id.vendor_id == 0x1234 && id.device_id == 0x1111) || (id.vendor_id == 0x80ee && id.device_id == 0xbeef)) - bxvga_found = true; - }); - - if (bxvga_found) { - BXVGADevice::initialize(); - } else { - if (multiboot_info_ptr->framebuffer_type == MULTIBOOT_FRAMEBUFFER_TYPE_RGB || multiboot_info_ptr->framebuffer_type == MULTIBOOT_FRAMEBUFFER_TYPE_EGA_TEXT) { - new MBVGADevice( - PhysicalAddress((u32)(multiboot_info_ptr->framebuffer_addr)), - multiboot_info_ptr->framebuffer_pitch, - multiboot_info_ptr->framebuffer_width, - multiboot_info_ptr->framebuffer_height); - } else { - BXVGADevice::initialize(); - } - } - } + + GraphicsManagement::the().initialize(); USB::UHCIController::detect(); @@ -297,7 +274,7 @@ void init_stage2(void*) int error; // FIXME: It would be nicer to set the mode from userspace. - tty0->set_graphical(!is_text_mode); + tty0->set_graphical(!GraphicsManagement::the().is_text_mode_enabled()); RefPtr<Thread> thread; auto userspace_init = kernel_command_line().userspace_init(); auto init_args = kernel_command_line().userspace_init_args(); |