Switch into 1024x768x32bpp VESA LFB mode at boot.

This is going to be pretty cool once I can hook up the Widgets/ code to it.
This commit is contained in:
Andreas Kling 2019-01-09 02:29:11 +01:00
parent 9963da9005
commit 659c54e32b
9 changed files with 172 additions and 2 deletions

View file

@ -9,6 +9,43 @@ boot:
mov ss, ax
mov sp, 0xffff
; get vesa modes
mov ax, 0x4f00
xor dx, dx
mov es, dx
mov di, 0xc000
mov [es:di], byte 'V'
mov [es:di+1], byte 'B'
mov [es:di+2], byte 'E'
mov [es:di+3], byte '2'
int 0x10
cmp ax, 0x004f
jne fug
cmp [es:di], byte 'V'
jne fug
cmp [es:di+1], byte 'E'
jne fug
cmp [es:di+2], byte 'S'
jne fug
cmp [es:di+3], byte 'A'
jne fug
; get vesa info
mov ax, 0x4f01
mov cx, 0x144
xor dx, dx
mov es, dx
mov di, 0x2000
int 0x10
cmp ax, 0x004f
jne fug
mov ax, 0x4f02
mov bx, 0x4144
int 0x10
cmp ax, 0x004f
jne fug
push cs
pop ds
xor bx, bx

View file

@ -24,7 +24,8 @@ KERNEL_OBJS = \
DoubleBuffer.o \
ELFImage.o \
ELFLoader.o \
KSyms.o
KSyms.o \
WindowComposer.o
VFS_OBJS = \
../VirtualFileSystem/DiskDevice.o \
@ -40,13 +41,17 @@ VFS_OBJS = \
../VirtualFileSystem/FileDescriptor.o \
../VirtualFileSystem/SyntheticFileSystem.o
WIDGETS_OBJS = \
../Widgets/Window.o \
../Widgets/Painter.o
AK_OBJS = \
../AK/String.o \
../AK/StringImpl.o \
../AK/StringBuilder.o \
../AK/FileSystemPath.o
OBJS = $(KERNEL_OBJS) $(VFS_OBJS) $(AK_OBJS) $(ELFLOADER_OBJS)
OBJS = $(KERNEL_OBJS) $(VFS_OBJS) $(AK_OBJS) $(WIDGETS_OBJS)
NASM = nasm
KERNEL = kernel

View file

@ -652,6 +652,12 @@ RetainPtr<VMObject> VMObject::create_anonymous(size_t size)
return adopt(*new VMObject(size));
}
RetainPtr<VMObject> VMObject::create_framebuffer_wrapper(PhysicalAddress paddr, size_t size)
{
size = ceilDiv(size, PAGE_SIZE) * PAGE_SIZE;
return adopt(*new VMObject(paddr, size));
}
RetainPtr<VMObject> VMObject::clone()
{
return adopt(*new VMObject(*this));
@ -676,6 +682,18 @@ VMObject::VMObject(size_t size)
m_physical_pages.resize(page_count());
}
VMObject::VMObject(PhysicalAddress paddr, size_t size)
: m_anonymous(true)
, m_size(size)
{
MM.register_vmo(*this);
for (size_t i = 0; i < size; i += PAGE_SIZE) {
m_physical_pages.append(adopt(*new PhysicalPage(paddr.offset(i), false)));
}
ASSERT(m_physical_pages.size() == page_count());
}
VMObject::VMObject(RetainPtr<Vnode>&& vnode, size_t size)
: m_size(size)
, m_vnode(move(vnode))

View file

@ -23,6 +23,7 @@ class PhysicalPage {
AK_MAKE_ETERNAL
friend class MemoryManager;
friend class PageDirectory;
friend class VMObject;
public:
PhysicalAddress paddr() const { return m_paddr; }
@ -73,6 +74,7 @@ class VMObject : public Retainable<VMObject> {
public:
static RetainPtr<VMObject> create_file_backed(RetainPtr<Vnode>&&, size_t);
static RetainPtr<VMObject> create_anonymous(size_t);
static RetainPtr<VMObject> create_framebuffer_wrapper(PhysicalAddress, size_t);
RetainPtr<VMObject> clone();
~VMObject();
@ -93,6 +95,7 @@ private:
VMObject(RetainPtr<Vnode>&&, size_t);
explicit VMObject(VMObject&);
explicit VMObject(size_t);
VMObject(PhysicalAddress, size_t);
String m_name;
bool m_anonymous { false };
Unix::off_t m_vnode_offset { 0 };

View file

@ -1811,3 +1811,76 @@ Unix::clock_t Process::sys$times(Unix::tms* times)
times->tms_cstime = m_ticks_in_kernel_for_dead_children;
return 0;
}
struct vbe_info_structure {
char signature[4]; // must be "VESA" to indicate valid VBE support
word version; // VBE version; high byte is major version, low byte is minor version
dword oem; // segment:offset pointer to OEM
dword capabilities; // bitfield that describes card capabilities
dword video_modes; // segment:offset pointer to list of supported video modes
word video_memory; // amount of video memory in 64KB blocks
word software_rev; // software revision
dword vendor; // segment:offset to card vendor string
dword product_name; // segment:offset to card model name
dword product_rev; // segment:offset pointer to product revision
char reserved[222]; // reserved for future expansion
char oem_data[256]; // OEM BIOSes store their strings in this area
} __attribute__ ((packed));
struct vbe_mode_info_structure {
word attributes; // deprecated, only bit 7 should be of interest to you, and it indicates the mode supports a linear frame buffer.
byte window_a; // deprecated
byte window_b; // deprecated
word granularity; // deprecated; used while calculating bank numbers
word window_size;
word segment_a;
word segment_b;
dword win_func_ptr; // deprecated; used to switch banks from protected mode without returning to real mode
word pitch; // number of bytes per horizontal line
word width; // width in pixels
word height; // height in pixels
byte w_char; // unused...
byte y_char; // ...
byte planes;
byte bpp; // bits per pixel in this mode
byte banks; // deprecated; total number of banks in this mode
byte memory_model;
byte bank_size; // deprecated; size of a bank, almost always 64 KB but may be 16 KB...
byte image_pages;
byte reserved0;
byte red_mask;
byte red_position;
byte green_mask;
byte green_position;
byte blue_mask;
byte blue_position;
byte reserved_mask;
byte reserved_position;
byte direct_color_attributes;
dword framebuffer; // physical address of the linear frame buffer; write here to draw to the screen
dword off_screen_mem_off;
word off_screen_mem_size; // size of memory in the framebuffer but not being displayed on the screen
byte reserved1[206];
} __attribute__ ((packed));
DisplayInfo Process::get_display_info()
{
DisplayInfo info;
//auto* vinfo = reinterpret_cast<vbe_info_structure*>(0xc000);
auto* vmode = reinterpret_cast<vbe_mode_info_structure*>(0x2000);
dbgprintf("VESA framebuffer, %ux%u, %u bpp @ P%x\n", vmode->width, vmode->height, vmode->bpp, vmode->framebuffer);
dbgprintf("Returning display info in %s<%u>\n", name().characters(), pid());
info.width = vmode->width;
info.height = vmode->height;
info.bpp = vmode->bpp;
info.pitch = vmode->pitch;
size_t framebuffer_size = info.pitch * info.height;
if (!m_display_framebuffer_region) {
auto framebuffer_vmo = VMObject::create_framebuffer_wrapper(PhysicalAddress(vmode->framebuffer), framebuffer_size);
m_display_framebuffer_region = allocate_region_with_vmo(LinearAddress(0xe0000000), framebuffer_size, move(framebuffer_vmo), 0, "framebuffer", true, true);
}
info.framebuffer = m_display_framebuffer_region->linearAddress.asPtr();
return info;
}

View file

@ -32,6 +32,14 @@ struct SignalActionData {
LinearAddress restorer;
};
struct DisplayInfo {
unsigned width;
unsigned height;
unsigned bpp;
unsigned pitch;
byte* framebuffer;
};
class Process : public InlineLinkedListNode<Process> {
friend class InlineLinkedListNode<Process>;
public:
@ -175,6 +183,8 @@ public:
Unix::clock_t sys$times(Unix::tms*);
int sys$utime(const char* pathname, const struct Unix::utimbuf*);
DisplayInfo get_display_info();
static void initialize();
void crash() NORETURN;
@ -317,6 +327,8 @@ private:
Region* m_stack_region { nullptr };
Region* m_signal_stack_user_region { nullptr };
Region* m_signal_stack_kernel_region { nullptr };
RetainPtr<Region> m_display_framebuffer_region;
};
extern Process* current;

12
Kernel/WindowComposer.cpp Normal file
View file

@ -0,0 +1,12 @@
#include "WindowComposer.h"
#include "Process.h"
void WindowComposer_main()
{
auto info = current->get_display_info();
dbgprintf("Entering WindowComposer main loop.\n");
for (;;) {
}
}

7
Kernel/WindowComposer.h Normal file
View file

@ -0,0 +1,7 @@
#pragma once
class WindowComposer {
public:
};

View file

@ -102,6 +102,9 @@ static void init_stage2()
Process::create_kernel_process("spawn_stress", spawn_stress);
#endif
extern void WindowComposer_main();
Process::create_kernel_process("WindowComposer", WindowComposer_main);
current->sys$exit(0);
ASSERT_NOT_REACHED();
}