dev: boot framebuffer support
This commit is contained in:
@@ -16,6 +16,9 @@ extern "C" {
|
|||||||
|
|
||||||
extern int ml_init(uintptr_t arg);
|
extern int ml_init(uintptr_t arg);
|
||||||
|
|
||||||
|
extern const struct framebuffer_varinfo *bootfb_varinfo(void);
|
||||||
|
extern const struct framebuffer_fixedinfo *bootfb_fixedinfo(void);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -20,6 +20,8 @@
|
|||||||
#define PTR32(x) ((void *)((uintptr_t)(x)))
|
#define PTR32(x) ((void *)((uintptr_t)(x)))
|
||||||
|
|
||||||
static ml_cpu_block g_bootstrap_cpu = {0};
|
static ml_cpu_block g_bootstrap_cpu = {0};
|
||||||
|
static struct framebuffer_varinfo __bootfb_varinfo;
|
||||||
|
static struct framebuffer_fixedinfo __bootfb_fixedinfo;
|
||||||
|
|
||||||
/* start and end of kernel image (physical addresses) */
|
/* start and end of kernel image (physical addresses) */
|
||||||
extern char __pstart[], __pend[];
|
extern char __pstart[], __pend[];
|
||||||
@@ -44,10 +46,51 @@ static void early_vm_init(void)
|
|||||||
printk("memblock: reserved bios+kernel at [0x%016llx-0x%016llx]", 0, (uintptr_t)__pend);
|
printk("memblock: reserved bios+kernel at [0x%016llx-0x%016llx]", 0, (uintptr_t)__pend);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void init_bootfb(multiboot_info_t *mb)
|
||||||
|
{
|
||||||
|
__bootfb_varinfo.fb_xres = mb->framebuffer_width;
|
||||||
|
__bootfb_varinfo.fb_yres = mb->framebuffer_height;
|
||||||
|
__bootfb_varinfo.fb_bpp = mb->framebuffer_bpp;
|
||||||
|
__bootfb_varinfo.fb_stride = mb->framebuffer_pitch;
|
||||||
|
|
||||||
|
switch (mb->framebuffer_type) {
|
||||||
|
case MULTIBOOT_FRAMEBUFFER_TYPE_INDEXED:
|
||||||
|
__bootfb_varinfo.fb_flags = FB_MODE_PALETTE;
|
||||||
|
__bootfb_varinfo.fb_palette_addr = mb->framebuffer_palette_addr;
|
||||||
|
__bootfb_varinfo.fb_palette_nr_colours = mb->framebuffer_palette_num_colors;
|
||||||
|
break;
|
||||||
|
case MULTIBOOT_FRAMEBUFFER_TYPE_RGB:
|
||||||
|
__bootfb_varinfo.fb_flags = FB_MODE_RGB;
|
||||||
|
__bootfb_varinfo.fb_red.b_length = mb->framebuffer_red_mask_size;
|
||||||
|
__bootfb_varinfo.fb_red.b_offset = mb->framebuffer_red_field_position;
|
||||||
|
|
||||||
|
__bootfb_varinfo.fb_green.b_length = mb->framebuffer_green_mask_size;
|
||||||
|
__bootfb_varinfo.fb_green.b_offset = mb->framebuffer_green_field_position;
|
||||||
|
|
||||||
|
__bootfb_varinfo.fb_blue.b_length = mb->framebuffer_blue_mask_size;
|
||||||
|
__bootfb_varinfo.fb_blue.b_offset = mb->framebuffer_blue_field_position;
|
||||||
|
|
||||||
|
__bootfb_varinfo.fb_alpha.b_length = 0;
|
||||||
|
__bootfb_varinfo.fb_alpha.b_offset = 0;
|
||||||
|
break;
|
||||||
|
case MULTIBOOT_FRAMEBUFFER_TYPE_EGA_TEXT:
|
||||||
|
__bootfb_varinfo.fb_flags = FB_MODE_VGATEXT;
|
||||||
|
__bootfb_varinfo.fb_xcells = 80;
|
||||||
|
__bootfb_varinfo.fb_ycells = 25;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
__bootfb_fixedinfo.fb_baseptr = mb->framebuffer_addr;
|
||||||
|
}
|
||||||
|
|
||||||
int ml_init(uintptr_t arg)
|
int ml_init(uintptr_t arg)
|
||||||
{
|
{
|
||||||
multiboot_info_t *mb = (multiboot_info_t *)arg;
|
multiboot_info_t *mb = (multiboot_info_t *)arg;
|
||||||
|
|
||||||
|
init_bootfb(mb);
|
||||||
|
|
||||||
bootstrap_cpu_init();
|
bootstrap_cpu_init();
|
||||||
vgacon_init();
|
vgacon_init();
|
||||||
serialcon_init(115200);
|
serialcon_init(115200);
|
||||||
@@ -56,6 +99,7 @@ int ml_init(uintptr_t arg)
|
|||||||
print_kernel_banner();
|
print_kernel_banner();
|
||||||
|
|
||||||
early_vm_init();
|
early_vm_init();
|
||||||
|
printk("video mode: %ux%u", mb->framebuffer_width, mb->framebuffer_height);
|
||||||
|
|
||||||
e820_scan(PTR32(mb->mmap_addr), mb->mmap_length);
|
e820_scan(PTR32(mb->mmap_addr), mb->mmap_length);
|
||||||
|
|
||||||
@@ -91,3 +135,13 @@ int ml_init(uintptr_t arg)
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const struct framebuffer_varinfo *bootfb_varinfo(void)
|
||||||
|
{
|
||||||
|
return &__bootfb_varinfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
const struct framebuffer_fixedinfo *bootfb_fixedinfo(void)
|
||||||
|
{
|
||||||
|
return &__bootfb_fixedinfo;
|
||||||
|
}
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ struct bus_device_ops {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct framebuffer_device_ops {
|
struct framebuffer_device_ops {
|
||||||
kern_status_t(*scan)(struct device *);
|
kern_status_t(*set_varinfo)(struct device *, const struct framebuffer_varinfo *);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct block_device {
|
struct block_device {
|
||||||
|
|||||||
@@ -4,7 +4,9 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
enum framebuffer_flags {
|
enum framebuffer_flags {
|
||||||
FB_VGATEXT = 0x01u,
|
FB_MODE_RGB = 0x01u,
|
||||||
|
FB_MODE_VGATEXT = 0x02u,
|
||||||
|
FB_MODE_PALETTE = 0x04u,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct framebuffer_bitfield {
|
struct framebuffer_bitfield {
|
||||||
@@ -20,12 +22,26 @@ struct framebuffer_varinfo {
|
|||||||
uint32_t fb_bpp;
|
uint32_t fb_bpp;
|
||||||
uint32_t fb_stride;
|
uint32_t fb_stride;
|
||||||
|
|
||||||
|
union {
|
||||||
|
struct {
|
||||||
|
uint32_t fb_xcells;
|
||||||
|
uint32_t fb_ycells;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct {
|
||||||
struct framebuffer_bitfield fb_red;
|
struct framebuffer_bitfield fb_red;
|
||||||
struct framebuffer_bitfield fb_green;
|
struct framebuffer_bitfield fb_green;
|
||||||
struct framebuffer_bitfield fb_blue;
|
struct framebuffer_bitfield fb_blue;
|
||||||
struct framebuffer_bitfield fb_alpha;
|
struct framebuffer_bitfield fb_alpha;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct {
|
||||||
|
uintptr_t fb_palette_addr;
|
||||||
|
uint16_t fb_palette_nr_colours;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
struct framebuffer_fixedinfo {
|
struct framebuffer_fixedinfo {
|
||||||
uint64_t fb_baseptr;
|
uint64_t fb_baseptr;
|
||||||
};
|
};
|
||||||
|
|||||||
18
init/main.c
18
init/main.c
@@ -182,14 +182,28 @@ void kernel_init(uintptr_t arg)
|
|||||||
|
|
||||||
printk("kernel_init() running on processor %u", this_cpu());
|
printk("kernel_init() running on processor %u", this_cpu());
|
||||||
|
|
||||||
|
|
||||||
create_kernel_thread(background_thread);
|
create_kernel_thread(background_thread);
|
||||||
|
|
||||||
|
struct object *fb;
|
||||||
struct object *kbd;
|
struct object *kbd;
|
||||||
|
|
||||||
run_all_tests();
|
run_all_tests();
|
||||||
|
|
||||||
status = object_namespace_get_object(global_namespace(), "/dev/input/input0", &kbd);
|
status = object_get("/dev/video/fb0", &fb);
|
||||||
|
if (status == KERN_OK) {
|
||||||
|
struct device *fb_dev = cast_to_device(fb);
|
||||||
|
struct framebuffer_device *fb_info = FRAMEBUFFER_DEVICE(fb_dev);
|
||||||
|
|
||||||
|
printk("fb: mode=%ux%ux%u type=%u cells=%ux%u",
|
||||||
|
fb_info->fb_varinfo.fb_xres, fb_info->fb_varinfo.fb_yres,
|
||||||
|
fb_info->fb_varinfo.fb_flags,
|
||||||
|
fb_info->fb_varinfo.fb_xcells, fb_info->fb_varinfo.fb_ycells);
|
||||||
|
} else {
|
||||||
|
printk("fb: unavailable");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status = object_get("/dev/input/input0", &kbd);
|
||||||
if (status != KERN_OK) {
|
if (status != KERN_OK) {
|
||||||
printk("no keyboard available");
|
printk("no keyboard available");
|
||||||
hang();
|
hang();
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
name: vgafb
|
name: vesafb
|
||||||
description: |
|
description: |
|
||||||
Generic VGA driver.
|
Boot-time VESA framebuffer driver.
|
||||||
id: net.doorstuck.socks.vgafb
|
id: net.doorstuck.socks.vesafb
|
||||||
license: BSD-3-Clause
|
license: BSD-3-Clause
|
||||||
copyright: Copyright © Max Wash 2023
|
copyright: Copyright © Max Wash 2023
|
||||||
sources:
|
sources:
|
||||||
65
kexts/drivers/video/vesafb/main.c
Normal file
65
kexts/drivers/video/vesafb/main.c
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
#include <socks/printk.h>
|
||||||
|
#include <socks/device.h>
|
||||||
|
#include <socks/kext.h>
|
||||||
|
#include <socks/machine/init.h>
|
||||||
|
#include <socks/libc/stdio.h>
|
||||||
|
|
||||||
|
static struct driver *vesa_driver = NULL;
|
||||||
|
static struct framebuffer_device *vesafb = NULL;
|
||||||
|
|
||||||
|
static kern_status_t set_varinfo(struct device *dev, const struct framebuffer_varinfo *info)
|
||||||
|
{
|
||||||
|
return KERN_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct framebuffer_device_ops vesa_ops = {
|
||||||
|
.set_varinfo = set_varinfo,
|
||||||
|
};
|
||||||
|
|
||||||
|
static void init_vesa(struct framebuffer_device *dev)
|
||||||
|
{
|
||||||
|
struct framebuffer_varinfo *varinfo = &dev->fb_varinfo;
|
||||||
|
struct framebuffer_fixedinfo *fixedinfo = &dev->fb_fixedinfo;
|
||||||
|
|
||||||
|
memcpy(varinfo, bootfb_varinfo(), sizeof *varinfo);
|
||||||
|
memcpy(fixedinfo, bootfb_fixedinfo(), sizeof *fixedinfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
static kern_status_t online(struct kext *self)
|
||||||
|
{
|
||||||
|
const struct framebuffer_fixedinfo *fixedinfo = bootfb_fixedinfo();
|
||||||
|
if (!fixedinfo->fb_baseptr) {
|
||||||
|
/* No VESA information avaiable, cannot create device. */
|
||||||
|
return KERN_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
vesa_driver = driver_create(self, "vesafb");
|
||||||
|
if (!vesa_driver) {
|
||||||
|
return KERN_NO_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
driver_register(vesa_driver);
|
||||||
|
|
||||||
|
struct framebuffer_device *fb = framebuffer_device_create();
|
||||||
|
fb->fb_ops = &vesa_ops;
|
||||||
|
|
||||||
|
init_vesa(fb);
|
||||||
|
|
||||||
|
struct device *fb_base = framebuffer_device_base(fb);
|
||||||
|
snprintf(fb_base->dev_name, sizeof fb_base->dev_name, "vesafb");
|
||||||
|
|
||||||
|
kern_status_t status = device_register(fb_base, vesa_driver, misc_device());
|
||||||
|
if (status != KERN_OK) {
|
||||||
|
driver_unregister(vesa_driver);
|
||||||
|
driver_destroy(vesa_driver);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
vesafb = fb;
|
||||||
|
|
||||||
|
return KERN_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFINE_KEXT("net.doorstuck.socks.vesafb",
|
||||||
|
online, NULL,
|
||||||
|
KEXT_NO_DEPENDENCIES);
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
name: vga16fb
|
|
||||||
description: |
|
|
||||||
Legacy VGA textmode framebuffer driver.
|
|
||||||
id: net.doorstuck.socks.vga16fb
|
|
||||||
license: BSD-3-Clause
|
|
||||||
copyright: Copyright © Max Wash 2023
|
|
||||||
sources:
|
|
||||||
- main.c
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
#include <socks/printk.h>
|
|
||||||
#include <socks/kext.h>
|
|
||||||
|
|
||||||
static kern_status_t online(struct kext *self)
|
|
||||||
{
|
|
||||||
printk("vga16fb: online");
|
|
||||||
return KERN_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
DEFINE_KEXT("net.doorstuck.socks.vga16fb",
|
|
||||||
online, NULL,
|
|
||||||
KEXT_NO_DEPENDENCIES);
|
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
#include <socks/printk.h>
|
|
||||||
#include <socks/device.h>
|
|
||||||
#include <socks/kext.h>
|
|
||||||
#include <socks/libc/stdio.h>
|
|
||||||
|
|
||||||
static struct driver *vga_driver = NULL;
|
|
||||||
static struct framebuffer_device *vgafb = NULL;
|
|
||||||
|
|
||||||
static kern_status_t online(struct kext *self)
|
|
||||||
{
|
|
||||||
vga_driver = driver_create(self, "vgafb");
|
|
||||||
if (!vga_driver) {
|
|
||||||
return KERN_NO_MEMORY;
|
|
||||||
}
|
|
||||||
|
|
||||||
driver_register(vga_driver);
|
|
||||||
|
|
||||||
struct framebuffer_device *fb = framebuffer_device_create();
|
|
||||||
struct device *fb_base = framebuffer_device_base(fb);
|
|
||||||
snprintf(fb_base->dev_name, sizeof fb_base->dev_name, "vgafb");
|
|
||||||
|
|
||||||
kern_status_t status = device_register(fb_base, vga_driver, misc_device());
|
|
||||||
if (status != KERN_OK) {
|
|
||||||
driver_unregister(vga_driver);
|
|
||||||
driver_destroy(vga_driver);
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
vgafb = fb;
|
|
||||||
|
|
||||||
return KERN_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
DEFINE_KEXT("net.doorstuck.socks.vgafb",
|
|
||||||
online, NULL,
|
|
||||||
KEXT_NO_DEPENDENCIES);
|
|
||||||
Reference in New Issue
Block a user