mirror of
https://github.com/RGBCube/serenity
synced 2025-07-27 09:07:45 +00:00
Kernel: Implement generic VGA device using multiboot info
This implements a very basic VGA device using the information provided to us by the bootloader in the multiboot header. This allows Serenity to boot to the desktop on basically any halfway modern system.
This commit is contained in:
parent
23b6ef29dd
commit
b957c61e6f
5 changed files with 148 additions and 4 deletions
102
Kernel/Devices/MBVGADevice.cpp
Normal file
102
Kernel/Devices/MBVGADevice.cpp
Normal file
|
@ -0,0 +1,102 @@
|
|||
#include <Kernel/Devices/MBVGADevice.h>
|
||||
#include <Kernel/Process.h>
|
||||
#include <Kernel/VM/AnonymousVMObject.h>
|
||||
#include <Kernel/VM/MemoryManager.h>
|
||||
#include <LibC/errno_numbers.h>
|
||||
#include <LibC/sys/ioctl_numbers.h>
|
||||
|
||||
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<Region*> 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();
|
||||
}
|
31
Kernel/Devices/MBVGADevice.h
Normal file
31
Kernel/Devices/MBVGADevice.h
Normal file
|
@ -0,0 +1,31 @@
|
|||
#pragma once
|
||||
|
||||
#include <AK/AKString.h>
|
||||
#include <AK/Types.h>
|
||||
#include <Kernel/Devices/BlockDevice.h>
|
||||
#include <Kernel/VM/PhysicalAddress.h>
|
||||
|
||||
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<Region*> 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 };
|
||||
};
|
Loading…
Add table
Add a link
Reference in a new issue