From 4cd9ebcb4f8e9aa0030996440ce4b08e854468a4 Mon Sep 17 00:00:00 2001 From: Max Wash Date: Sat, 10 Jun 2023 21:41:46 +0100 Subject: [PATCH] kexts: add generic vga/fb tty driver --- arch/x86_64/init.c | 14 ++- kexts/drivers/tty/fbcon/extension.yaml | 10 ++ kexts/drivers/tty/fbcon/fbcon.c | 91 +++++++++++++++ kexts/drivers/tty/fbcon/fbcon.h | 24 ++++ kexts/drivers/tty/fbcon/include/socks/fbcon.h | 11 ++ kexts/drivers/tty/fbcon/main.c | 110 ++++++++++++++++++ .../drivers/tty/fbcon}/vgacon.c | 96 ++++++++++++++- kexts/drivers/tty/serialcon/extension.yaml | 8 ++ kexts/drivers/tty/serialcon/main.c | 38 ++++++ 9 files changed, 395 insertions(+), 7 deletions(-) create mode 100644 kexts/drivers/tty/fbcon/extension.yaml create mode 100644 kexts/drivers/tty/fbcon/fbcon.c create mode 100644 kexts/drivers/tty/fbcon/fbcon.h create mode 100644 kexts/drivers/tty/fbcon/include/socks/fbcon.h create mode 100644 kexts/drivers/tty/fbcon/main.c rename {arch/x86_64 => kexts/drivers/tty/fbcon}/vgacon.c (61%) create mode 100644 kexts/drivers/tty/serialcon/extension.yaml create mode 100644 kexts/drivers/tty/serialcon/main.c diff --git a/arch/x86_64/init.c b/arch/x86_64/init.c index 37f6a4c..aaf6c26 100644 --- a/arch/x86_64/init.c +++ b/arch/x86_64/init.c @@ -1,5 +1,6 @@ #include #include +#include #include #include #include @@ -20,6 +21,10 @@ #include #endif +#ifdef KEXT_NET_DOORSTUCK_SOCKS_FBCON +#include +#endif + #define PTR32(x) ((void *)((uintptr_t)(x))) static ml_cpu_block g_bootstrap_cpu = {0}; @@ -56,6 +61,8 @@ static void init_bootfb(multiboot_info_t *mb) __bootfb_varinfo.fb_bpp = mb->framebuffer_bpp; __bootfb_varinfo.fb_stride = mb->framebuffer_pitch; + __bootfb_fixedinfo.fb_baseptr = mb->framebuffer_addr; + switch (mb->framebuffer_type) { case MULTIBOOT_FRAMEBUFFER_TYPE_INDEXED: __bootfb_varinfo.fb_flags = FB_MODE_PALETTE; @@ -77,6 +84,7 @@ static void init_bootfb(multiboot_info_t *mb) __bootfb_varinfo.fb_alpha.b_offset = 0; break; case MULTIBOOT_FRAMEBUFFER_TYPE_EGA_TEXT: + __bootfb_fixedinfo.fb_baseptr = 0xb8000; __bootfb_varinfo.fb_flags = FB_MODE_VGATEXT; __bootfb_varinfo.fb_xcells = 80; __bootfb_varinfo.fb_ycells = 25; @@ -84,8 +92,6 @@ static void init_bootfb(multiboot_info_t *mb) default: break; } - - __bootfb_fixedinfo.fb_baseptr = mb->framebuffer_addr; } static void use_uniprocessor_topology(void) @@ -101,7 +107,7 @@ int ml_init(uintptr_t arg) init_bootfb(mb); bootstrap_cpu_init(); - vgacon_init(); + early_vgacon_init(); serialcon_init(115200); clock_calibrate(500); @@ -148,6 +154,8 @@ int ml_init(uintptr_t arg) acpi_init(); #endif + tty_init(); + ml_int_enable(); return 0; diff --git a/kexts/drivers/tty/fbcon/extension.yaml b/kexts/drivers/tty/fbcon/extension.yaml new file mode 100644 index 0000000..4e03917 --- /dev/null +++ b/kexts/drivers/tty/fbcon/extension.yaml @@ -0,0 +1,10 @@ +name: fbcon +description: | + VGA/Framebuffer kernel console. +id: net.doorstuck.socks.fbcon +license: BSD-3-Clause +copyright: Copyright © Max Wash 2023 +sources: + - main.c + - fbcon.c + - vgacon.c diff --git a/kexts/drivers/tty/fbcon/fbcon.c b/kexts/drivers/tty/fbcon/fbcon.c new file mode 100644 index 0000000..0118fd2 --- /dev/null +++ b/kexts/drivers/tty/fbcon/fbcon.c @@ -0,0 +1,91 @@ +#include +#include "fbcon.h" + +#define CELL_WIDTH 8 +#define CELL_HEIGHT 16 + +static void fbcon_init(struct device *dev) +{ + +} + +static void fbcon_deinit(struct device *dev) +{ + +} + +static void fbcon_clear(struct device *dev, int x, int y, int width, int height) +{ + +} + +static void fbcon_putc(struct device *dev, int c, int xpos, int ypos, tty_attrib_t attrib) +{ + +} + +static void fbcon_set_cursor(struct device *dev, enum tty_cursor cur) +{ + +} + +static void fbcon_move_cursor(struct device *dev, int x, int y) +{ + +} + +static void fbcon_scroll(struct device *dev, enum tty_scroll_dir dir, int lines) +{ + +} + + +static struct tty_driver_ops fbcon_ops = { + .tty_init = fbcon_init, + .tty_deinit = fbcon_deinit, + .tty_clear = fbcon_clear, + .tty_putc = fbcon_putc, + .tty_set_cursor = fbcon_set_cursor, + .tty_move_cursor = fbcon_move_cursor, + .tty_scroll = fbcon_scroll, +}; + +kern_status_t init_fbcon_console(struct device *tty, struct device *fb) +{ + struct char_device *cdev = CHAR_DEVICE(tty); + struct framebuffer_varinfo fb_mode; + struct framebuffer_fixedinfo fixedinfo; + struct tty_device *ttydev = cdev->c_tty; + + struct fbcon_priv *priv = kmalloc(sizeof *priv, VM_NORMAL); + if (!priv) { + return KERN_NO_MEMORY; + } + + kern_status_t status = framebuffer_get_varinfo(fb, &fb_mode); + + if (status != KERN_OK) { + kfree(priv); + return status; + } + + status = framebuffer_get_fixedinfo(fb, &fixedinfo); + + if (status != KERN_OK) { + kfree(priv); + return status; + } + + ttydev->tty_xcells = fb_mode.fb_xres / CELL_WIDTH; + ttydev->tty_ycells = fb_mode.fb_yres / CELL_HEIGHT; + ttydev->tty_xcur = 0; + ttydev->tty_ycur = 0; + + priv->fbdev = fb; + priv->fb_pitch = fb_mode.fb_stride; + priv->fb_pixels = vm_phys_to_virt(fixedinfo.fb_baseptr); + priv->tty_ops = &fbcon_ops; + tty->dev_priv = priv; + + return KERN_OK; +} diff --git a/kexts/drivers/tty/fbcon/fbcon.h b/kexts/drivers/tty/fbcon/fbcon.h new file mode 100644 index 0000000..48f6a19 --- /dev/null +++ b/kexts/drivers/tty/fbcon/fbcon.h @@ -0,0 +1,24 @@ +#ifndef FBCON_H_ +#define FBCON_H_ + +#include +#include + +struct fbcon_priv { + struct device *fbdev; + union { + uint32_t *fb_pixels; + uint16_t *fb_cells; + }; + + unsigned long fb_pitch; + struct tty_driver_ops *tty_ops; +}; + +struct device; +struct tty_driver_ops; + +extern kern_status_t init_fbcon_console(struct device *tty, struct device *fb); +extern kern_status_t init_vgacon_console(struct device *tty, struct device *fb); + +#endif diff --git a/kexts/drivers/tty/fbcon/include/socks/fbcon.h b/kexts/drivers/tty/fbcon/include/socks/fbcon.h new file mode 100644 index 0000000..ae7a670 --- /dev/null +++ b/kexts/drivers/tty/fbcon/include/socks/fbcon.h @@ -0,0 +1,11 @@ +#ifndef SOCKS_FBCON_H_ +#define SOCKS_FBCON_H_ + +#include + +struct device; + +extern kern_status_t start_console_on_framebuffer(struct device *fb); +extern void early_vgacon_init(void); + +#endif diff --git a/kexts/drivers/tty/fbcon/main.c b/kexts/drivers/tty/fbcon/main.c new file mode 100644 index 0000000..fcdb99b --- /dev/null +++ b/kexts/drivers/tty/fbcon/main.c @@ -0,0 +1,110 @@ +#include +#include +#include +#include +#include +#include "fbcon.h" + +static struct tty_driver *fbcon_driver = NULL; +static struct device *tty0 = NULL; + +static void tty_console_write(struct console *con, const char *s, unsigned int len) +{ + if (!tty0) { + return; + } +} + +static int tty_console_read(struct console *con, char *s, unsigned int len) +{ + return 0; +} + +static struct console tty_console = { + .c_name = "tty0", + .c_write = tty_console_write, + .c_read = tty_console_read, +}; + +static void tty_clear(struct device *dev, int x, int y, int width, int height) +{ + struct fbcon_priv *priv = dev->dev_priv; + priv->tty_ops->tty_clear(dev, x, y, width, height); +} + +static void tty_putc(struct device *dev, int c, int xpos, int ypos, tty_attrib_t attrib) +{ + struct fbcon_priv *priv = dev->dev_priv; + priv->tty_ops->tty_putc(dev, c, xpos, ypos, attrib); +} + +static void tty_set_cursor(struct device *dev, enum tty_cursor cur) +{ + struct fbcon_priv *priv = dev->dev_priv; + priv->tty_ops->tty_set_cursor(dev, cur); +} + +static void tty_move_cursor(struct device *dev, int x, int y) +{ + struct fbcon_priv *priv = dev->dev_priv; + priv->tty_ops->tty_move_cursor(dev, x, y); +} + +static void tty_scroll(struct device *dev, enum tty_scroll_dir dir, int lines) +{ + struct fbcon_priv *priv = dev->dev_priv; + priv->tty_ops->tty_scroll(dev, dir, lines); +} + +static struct tty_driver_ops tty_ops = { + .tty_clear = tty_clear, + .tty_putc = tty_putc, + .tty_set_cursor = tty_set_cursor, + .tty_move_cursor = tty_move_cursor, + .tty_scroll = tty_scroll, +}; + +static kern_status_t online(struct kext *self) +{ + fbcon_driver = tty_driver_create(self, "tty"); + if (!fbcon_driver) { + return KERN_NO_MEMORY; + } + + fbcon_driver->tty_ops = &tty_ops; + + tty_driver_register(fbcon_driver); + console_register(&tty_console); + + return KERN_OK; +} + +kern_status_t start_console_on_framebuffer(struct device *fb) +{ + struct framebuffer_varinfo fb_mode; + framebuffer_get_varinfo(fb, &fb_mode); + + struct device *tty = tty_device_create(); + + kern_status_t status; + if (fb_mode.fb_flags & FB_MODE_VGATEXT) { + status = init_vgacon_console(tty, fb); + } else { + status = init_fbcon_console(tty, fb); + } + + if (status != KERN_OK) { + /* TODO destroy tty device */ + return status; + } + + if (!tty0) { + tty0 = tty; + } + + return status; +} + +DEFINE_KEXT("net.doorstuck.socks.fbcon", + online, NULL, + KEXT_NO_DEPENDENCIES); diff --git a/arch/x86_64/vgacon.c b/kexts/drivers/tty/fbcon/vgacon.c similarity index 61% rename from arch/x86_64/vgacon.c rename to kexts/drivers/tty/fbcon/vgacon.c index 2168817..105cbf2 100644 --- a/arch/x86_64/vgacon.c +++ b/kexts/drivers/tty/fbcon/vgacon.c @@ -1,3 +1,4 @@ +#include #include #include #include @@ -6,6 +7,7 @@ #include #include #include +#include "fbcon.h" #define VGA_PORT_CMD 0x3D4 #define VGA_PORT_DATA 0x3D5 @@ -108,14 +110,14 @@ static void vgacon_write(struct console *con, const char *s, unsigned int len) } } -static struct console vgacon = { +static struct console early_vgacon = { .c_name = "vgacon", .c_flags = CON_BOOT, .c_write = vgacon_write, .c_lock = SPIN_LOCK_INIT, }; -void vgacon_init(void) +void early_vgacon_init(void) { g_console_cursor_xpos = 0; g_console_cursor_ypos = 0; @@ -127,6 +129,92 @@ void vgacon_init(void) init_vga_cursor(); move_vga_cursor(g_console_cursor_xpos, g_console_cursor_ypos); - console_register(&vgacon); - early_printk_init(&vgacon); + console_register(&early_vgacon); + early_printk_init(&early_vgacon); +} + +static void vgacon_init(struct device *dev) +{ + +} + +static void vgacon_deinit(struct device *dev) +{ + +} + +static void vgacon_clear(struct device *dev, int x, int y, int width, int height) +{ + +} + +static void vgacon_putc(struct device *dev, int c, int xpos, int ypos, tty_attrib_t attrib) +{ + +} + +static void vgacon_set_cursor(struct device *dev, enum tty_cursor cur) +{ + +} + +static void vgacon_move_cursor(struct device *dev, int x, int y) +{ + +} + +static void vgacon_scroll(struct device *dev, enum tty_scroll_dir dir, int lines) +{ + +} + + +static struct tty_driver_ops vgacon_ops = { + .tty_init = vgacon_init, + .tty_deinit = vgacon_deinit, + .tty_clear = vgacon_clear, + .tty_putc = vgacon_putc, + .tty_set_cursor = vgacon_set_cursor, + .tty_move_cursor = vgacon_move_cursor, + .tty_scroll = vgacon_scroll, +}; + +kern_status_t init_vgacon_console(struct device *tty, struct device *fb) +{ + struct char_device *cdev = CHAR_DEVICE(tty); + struct framebuffer_varinfo fb_mode; + struct framebuffer_fixedinfo fixedinfo; + struct tty_device *ttydev = cdev->c_tty; + + struct fbcon_priv *priv = kmalloc(sizeof *priv, VM_NORMAL); + if (!priv) { + return KERN_NO_MEMORY; + } + + kern_status_t status = framebuffer_get_varinfo(fb, &fb_mode); + + if (status != KERN_OK) { + kfree(priv); + return status; + } + + status = framebuffer_get_fixedinfo(fb, &fixedinfo); + + if (status != KERN_OK) { + kfree(priv); + return status; + } + + ttydev->tty_xcells = fb_mode.fb_xcells; + ttydev->tty_ycells = fb_mode.fb_ycells; + ttydev->tty_xcur = 0; + ttydev->tty_ycur = 0; + + priv->fbdev = fb; + priv->fb_pitch = fb_mode.fb_stride; + priv->fb_pixels = vm_phys_to_virt(fixedinfo.fb_baseptr); + priv->tty_ops = &vgacon_ops; + tty->dev_priv = priv; + + return KERN_OK; } diff --git a/kexts/drivers/tty/serialcon/extension.yaml b/kexts/drivers/tty/serialcon/extension.yaml new file mode 100644 index 0000000..dee9bdc --- /dev/null +++ b/kexts/drivers/tty/serialcon/extension.yaml @@ -0,0 +1,8 @@ +name: serialcon +description: | + Serial port console. +id: net.doorstuck.socks.serialcon +license: BSD-3-Clause +copyright: Copyright © Max Wash 2023 +sources: + - main.c diff --git a/kexts/drivers/tty/serialcon/main.c b/kexts/drivers/tty/serialcon/main.c new file mode 100644 index 0000000..b7eecbb --- /dev/null +++ b/kexts/drivers/tty/serialcon/main.c @@ -0,0 +1,38 @@ +#include +#include +#include +#include +#include + +static struct tty_driver *serialcon_driver = NULL; + +static kern_status_t online(struct kext *self) +{ + serialcon_driver = tty_driver_create(self, "ttyS"); + if (!serialcon_driver) { + return KERN_NO_MEMORY; + } + + tty_driver_register(serialcon_driver); + + struct device *ttyS0 = tty_device_create(); + struct device *ttyS1 = tty_device_create(); + struct device *ttyS2 = tty_device_create(); + struct device *ttyS3 = tty_device_create(); + + snprintf(ttyS0->dev_name, sizeof ttyS0->dev_name, "ttyS0"); + snprintf(ttyS1->dev_name, sizeof ttyS1->dev_name, "ttyS1"); + snprintf(ttyS2->dev_name, sizeof ttyS2->dev_name, "ttyS2"); + snprintf(ttyS3->dev_name, sizeof ttyS3->dev_name, "ttyS3"); + + tty_device_register(ttyS0, serialcon_driver, misc_device()); + tty_device_register(ttyS1, serialcon_driver, misc_device()); + tty_device_register(ttyS2, serialcon_driver, misc_device()); + tty_device_register(ttyS3, serialcon_driver, misc_device()); + + return KERN_OK; +} + +DEFINE_KEXT("net.doorstuck.socks.serialcon", + online, NULL, + KEXT_NO_DEPENDENCIES);