diff --git a/arch/x86_64/include/socks/machine/init.h b/arch/x86_64/include/socks/machine/init.h index b425439..f1a0d35 100644 --- a/arch/x86_64/include/socks/machine/init.h +++ b/arch/x86_64/include/socks/machine/init.h @@ -16,6 +16,9 @@ extern "C" { 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 } #endif diff --git a/arch/x86_64/init.c b/arch/x86_64/init.c index 36ffaaa..0f25119 100644 --- a/arch/x86_64/init.c +++ b/arch/x86_64/init.c @@ -20,6 +20,8 @@ #define PTR32(x) ((void *)((uintptr_t)(x))) 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) */ 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); } +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) { multiboot_info_t *mb = (multiboot_info_t *)arg; + init_bootfb(mb); + bootstrap_cpu_init(); vgacon_init(); serialcon_init(115200); @@ -56,6 +99,7 @@ int ml_init(uintptr_t arg) print_kernel_banner(); early_vm_init(); + printk("video mode: %ux%u", mb->framebuffer_width, mb->framebuffer_height); e820_scan(PTR32(mb->mmap_addr), mb->mmap_length); @@ -91,3 +135,13 @@ int ml_init(uintptr_t arg) return 0; } + +const struct framebuffer_varinfo *bootfb_varinfo(void) +{ + return &__bootfb_varinfo; +} + +const struct framebuffer_fixedinfo *bootfb_fixedinfo(void) +{ + return &__bootfb_fixedinfo; +} diff --git a/include/socks/device.h b/include/socks/device.h index 059e632..306d3be 100644 --- a/include/socks/device.h +++ b/include/socks/device.h @@ -70,7 +70,7 @@ struct bus_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 { diff --git a/include/socks/fb.h b/include/socks/fb.h index 73f13c9..b94cd9f 100644 --- a/include/socks/fb.h +++ b/include/socks/fb.h @@ -4,7 +4,9 @@ #include enum framebuffer_flags { - FB_VGATEXT = 0x01u, + FB_MODE_RGB = 0x01u, + FB_MODE_VGATEXT = 0x02u, + FB_MODE_PALETTE = 0x04u, }; struct framebuffer_bitfield { @@ -20,10 +22,24 @@ struct framebuffer_varinfo { uint32_t fb_bpp; uint32_t fb_stride; - struct framebuffer_bitfield fb_red; - struct framebuffer_bitfield fb_green; - struct framebuffer_bitfield fb_blue; - struct framebuffer_bitfield fb_alpha; + union { + struct { + uint32_t fb_xcells; + uint32_t fb_ycells; + }; + + struct { + struct framebuffer_bitfield fb_red; + struct framebuffer_bitfield fb_green; + struct framebuffer_bitfield fb_blue; + struct framebuffer_bitfield fb_alpha; + }; + + struct { + uintptr_t fb_palette_addr; + uint16_t fb_palette_nr_colours; + }; + }; }; struct framebuffer_fixedinfo { diff --git a/init/main.c b/init/main.c index de86d28..7b16fc3 100644 --- a/init/main.c +++ b/init/main.c @@ -182,14 +182,28 @@ void kernel_init(uintptr_t arg) printk("kernel_init() running on processor %u", this_cpu()); - create_kernel_thread(background_thread); + struct object *fb; struct object *kbd; 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) { printk("no keyboard available"); hang(); diff --git a/kexts/drivers/video/vgafb/extension.yaml b/kexts/drivers/video/vesafb/extension.yaml similarity index 53% rename from kexts/drivers/video/vgafb/extension.yaml rename to kexts/drivers/video/vesafb/extension.yaml index e830555..c517319 100644 --- a/kexts/drivers/video/vgafb/extension.yaml +++ b/kexts/drivers/video/vesafb/extension.yaml @@ -1,7 +1,7 @@ -name: vgafb +name: vesafb description: | - Generic VGA driver. -id: net.doorstuck.socks.vgafb + Boot-time VESA framebuffer driver. +id: net.doorstuck.socks.vesafb license: BSD-3-Clause copyright: Copyright © Max Wash 2023 sources: diff --git a/kexts/drivers/video/vesafb/main.c b/kexts/drivers/video/vesafb/main.c new file mode 100644 index 0000000..f9543e6 --- /dev/null +++ b/kexts/drivers/video/vesafb/main.c @@ -0,0 +1,65 @@ +#include +#include +#include +#include +#include + +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); diff --git a/kexts/drivers/video/vga16fb/extension.yaml b/kexts/drivers/video/vga16fb/extension.yaml deleted file mode 100644 index 0548f5c..0000000 --- a/kexts/drivers/video/vga16fb/extension.yaml +++ /dev/null @@ -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 diff --git a/kexts/drivers/video/vga16fb/main.c b/kexts/drivers/video/vga16fb/main.c deleted file mode 100644 index c6fb71e..0000000 --- a/kexts/drivers/video/vga16fb/main.c +++ /dev/null @@ -1,12 +0,0 @@ -#include -#include - -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); diff --git a/kexts/drivers/video/vgafb/main.c b/kexts/drivers/video/vgafb/main.c deleted file mode 100644 index 29aad7f..0000000 --- a/kexts/drivers/video/vgafb/main.c +++ /dev/null @@ -1,36 +0,0 @@ -#include -#include -#include -#include - -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);