diff --git a/Kernel/Boot/boot.S b/Kernel/Boot/boot.S index d37bfe964b..10892fc4e1 100644 --- a/Kernel/Boot/boot.S +++ b/Kernel/Boot/boot.S @@ -1,7 +1,7 @@ .set MULTIBOOT_MAGIC, 0x1badb002 .set MULTIBOOT_PAGE_ALIGN, 0x1 .set MULTIBOOT_MEMORY_INFO, 0x2 -.set MULTIBOOT_VIDEO_MODE, 0x0 +.set MULTIBOOT_VIDEO_MODE, 0x4 .set multiboot_flags, MULTIBOOT_PAGE_ALIGN | MULTIBOOT_MEMORY_INFO | MULTIBOOT_VIDEO_MODE .set multiboot_checksum, -(MULTIBOOT_MAGIC + multiboot_flags) @@ -22,8 +22,8 @@ /* for MULTIBOOT_VIDEO_MODE */ .long 0x00000000 /* mode_type */ -.long 0 /* width */ -.long 0 /* height */ +.long 1024 /* width */ +.long 768 /* height */ .long 32 /* depth */ .section .stack, "aw", @nobits diff --git a/Kernel/Devices/MBVGADevice.cpp b/Kernel/Devices/MBVGADevice.cpp new file mode 100644 index 0000000000..a730fd25b6 --- /dev/null +++ b/Kernel/Devices/MBVGADevice.cpp @@ -0,0 +1,102 @@ +#include +#include +#include +#include +#include +#include + +static MBVGADevice* s_the; + +MBVGADevice& MBVGADevice::the() +{ + return *s_the; +} + +MBVGADevice::MBVGADevice(PhysicalAddress addr, int pitch, int width, int height) + : BlockDevice(29, 0) + , m_framebuffer_address(addr) + , m_framebuffer_pitch(pitch) + , m_framebuffer_width(width) + , m_framebuffer_height(height) +{ + s_the = this; +} + +KResultOr MBVGADevice::mmap(Process& process, FileDescription&, VirtualAddress preferred_vaddr, size_t offset, size_t size, int prot) +{ + ASSERT(offset == 0); + ASSERT(size == framebuffer_size_in_bytes()); + auto vmo = AnonymousVMObject::create_for_physical_range(m_framebuffer_address, framebuffer_size_in_bytes()); + auto* region = process.allocate_region_with_vmo( + preferred_vaddr, + framebuffer_size_in_bytes(), + move(vmo), + 0, + "MBVGA Framebuffer", + prot); + kprintf("MBVGA: %s(%u) created Region{%p} with size %u for framebuffer P%x with vaddr L%x\n", + process.name().characters(), process.pid(), + region, region->size(), m_framebuffer_address.as_ptr(), region->vaddr().get()); + ASSERT(region); + return region; +} + +int MBVGADevice::ioctl(FileDescription&, unsigned request, unsigned arg) +{ + switch (request) { + case FB_IOCTL_GET_SIZE_IN_BYTES: { + auto* out = (size_t*)arg; + if (!current->process().validate_write_typed(out)) + return -EFAULT; + *out = framebuffer_size_in_bytes(); + return 0; + } + case FB_IOCTL_GET_BUFFER: { + auto* index = (int*)arg; + if (!current->process().validate_write_typed(index)) + return -EFAULT; + *index = 0; + return 0; + } + case FB_IOCTL_GET_RESOLUTION: { + auto* resolution = (FBResolution*)arg; + if (!current->process().validate_write_typed(resolution)) + return -EFAULT; + resolution->pitch = m_framebuffer_pitch; + resolution->width = m_framebuffer_width; + resolution->height = m_framebuffer_height; + return 0; + } + case FB_IOCTL_SET_RESOLUTION: { + auto* resolution = (FBResolution*)arg; + if (!current->process().validate_read_typed(resolution) || !current->process().validate_write_typed(resolution)) + return -EFAULT; + resolution->pitch = m_framebuffer_pitch; + resolution->width = m_framebuffer_width; + resolution->height = m_framebuffer_height; + return 0; + } + default: + return -EINVAL; + }; +} + +bool MBVGADevice::can_read(FileDescription&) const +{ + ASSERT_NOT_REACHED(); +} + +bool MBVGADevice::can_write(FileDescription&) const +{ + ASSERT_NOT_REACHED(); +} + +ssize_t MBVGADevice::read(FileDescription&, u8*, ssize_t) +{ + ASSERT_NOT_REACHED(); +} + +ssize_t MBVGADevice::write(FileDescription&, const u8*, ssize_t) +{ + ASSERT_NOT_REACHED(); +} diff --git a/Kernel/Devices/MBVGADevice.h b/Kernel/Devices/MBVGADevice.h new file mode 100644 index 0000000000..b465d3ecce --- /dev/null +++ b/Kernel/Devices/MBVGADevice.h @@ -0,0 +1,31 @@ +#pragma once + +#include +#include +#include +#include + +class MBVGADevice final : public BlockDevice { + AK_MAKE_ETERNAL +public: + static MBVGADevice& the(); + + MBVGADevice(PhysicalAddress addr, int pitch, int width, int height); + + virtual int ioctl(FileDescription&, unsigned request, unsigned arg) override; + virtual KResultOr mmap(Process&, FileDescription&, VirtualAddress preferred_vaddr, size_t offset, size_t, int prot) override; + +private: + virtual const char* class_name() const override { return "MBVGA"; } + virtual bool can_read(FileDescription&) const override; + virtual bool can_write(FileDescription&) const override; + virtual ssize_t read(FileDescription&, u8*, ssize_t) override; + virtual ssize_t write(FileDescription&, const u8*, ssize_t) override; + + size_t framebuffer_size_in_bytes() const { return m_framebuffer_pitch * m_framebuffer_height; } + + PhysicalAddress m_framebuffer_address; + int m_framebuffer_pitch { 0 }; + int m_framebuffer_width { 0 }; + int m_framebuffer_height { 0 }; +}; diff --git a/Kernel/Makefile b/Kernel/Makefile index 97e1a17369..6afbf161fb 100644 --- a/Kernel/Makefile +++ b/Kernel/Makefile @@ -44,6 +44,7 @@ KERNEL_OBJS = \ FileSystem/SharedMemory.o \ FileSystem/DevPtsFS.o \ Devices/BXVGADevice.o \ + Devices/MBVGADevice.o \ PCI.o \ Devices/PS2MouseDevice.o \ Devices/SerialDevice.o \ diff --git a/Kernel/init.cpp b/Kernel/init.cpp index d90e6130ff..e8b2904645 100644 --- a/Kernel/init.cpp +++ b/Kernel/init.cpp @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -229,7 +230,16 @@ extern "C" [[noreturn]] void init() ); }); - new BXVGADevice; + if (multiboot_info_ptr->framebuffer_type == 1) { + 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 { + new BXVGADevice; + } auto e1000 = E1000NetworkAdapter::autodetect();