diff --git a/dev/core.c b/dev/core.c index d3abfd0..8b54a3d 100644 --- a/dev/core.c +++ b/dev/core.c @@ -19,6 +19,19 @@ static kern_status_t device_object_get_child_named(struct object *, const char * extern kern_status_t init_driver_tree(void); +extern struct device_type_ops input_type_ops; +extern struct device_type_ops framebuffer_type_ops; + +static struct device_type_ops *type_ops[] = { + [DEV_TYPE_UNKNOWN] = NULL, + [DEV_TYPE_BLOCK] = NULL, + [DEV_TYPE_CHAR] = NULL, + [DEV_TYPE_NET] = NULL, + [DEV_TYPE_INPUT] = &input_type_ops, + [DEV_TYPE_BUS] = NULL, + [DEV_TYPE_FRAMEBUFFER] = &framebuffer_type_ops, +}; + static struct object_type device_type = { .ob_name = "device", .ob_size = sizeof(struct device), @@ -60,7 +73,7 @@ kern_status_t device_init(void) struct bus_device *system_dev = bus_device_create(); struct device *system_dev_base = bus_device_base(system_dev); snprintf(system_dev_base->dev_name, sizeof system_dev_base->dev_name, "system"); - __root_device = bus_device_base(system_dev); + set_root_device(bus_device_base(system_dev)); struct bus_device *misc_dev = bus_device_create(); struct device *misc_dev_base = bus_device_base(misc_dev); @@ -236,14 +249,12 @@ kern_status_t device_register(struct device *dev, struct driver *owner, struct d driver_add_device(owner, dev); - switch (dev->dev_type) { - case DEV_TYPE_INPUT: - status = input_device_register(INPUT_DEVICE(dev)); - break; - default: - break; + if (type_ops[dev->dev_type] && type_ops[dev->dev_type]->register_device) { + status = type_ops[dev->dev_type]->register_device(dev); } + /* TODO remove device if registration failed */ + driver_unlock(owner); device_unlock_irqrestore(dev, flags); diff --git a/dev/fb.c b/dev/fb.c new file mode 100644 index 0000000..5a265e2 --- /dev/null +++ b/dev/fb.c @@ -0,0 +1,47 @@ +#include +#include +#include + +static DECLARE_BITMAP(fb_device_ids, FRAMEBUFFER_DEVICE_MAX); +static spin_lock_t fb_device_ids_lock = SPIN_LOCK_INIT; + +struct framebuffer_device *framebuffer_device_create(void) +{ + struct device *dev = device_alloc(); + if (!dev) { + return NULL; + } + + dev->dev_type = DEV_TYPE_FRAMEBUFFER; + + return FRAMEBUFFER_DEVICE(dev); +} + +static kern_status_t generate_name(struct framebuffer_device *dev, char out[DEV_NAME_MAX]) +{ + snprintf(out, DEV_NAME_MAX, "fb%u", dev->fb_id); + return KERN_OK; +} + +kern_status_t framebuffer_device_register(struct device *dev) +{ + unsigned long flags; + spin_lock_irqsave(&fb_device_ids_lock, &flags); + unsigned int id = bitmap_lowest_clear(fb_device_ids, INPUT_DEVICE_MAX); + bitmap_set(fb_device_ids, id); + spin_unlock_irqrestore(&fb_device_ids_lock, flags); + + struct framebuffer_device *fbdev = &dev->fb; + fbdev->fb_id = id; + + char name[DEV_NAME_MAX]; + generate_name(fbdev, name); + char path[OBJECT_PATH_MAX]; + snprintf(path, sizeof path, "/dev/video/%s", name); + + return object_namespace_create_link(global_namespace(), path, &dev->dev_base); +} + +struct device_type_ops framebuffer_type_ops = { + .register_device = framebuffer_device_register, +}; diff --git a/dev/input.c b/dev/input.c index bf7c7a8..5ce0747 100644 --- a/dev/input.c +++ b/dev/input.c @@ -61,7 +61,7 @@ static kern_status_t generate_name(struct input_device *dev, char out[DEV_NAME_M return KERN_OK; } -kern_status_t input_device_register(struct input_device *dev) +kern_status_t input_device_register(struct device *dev) { unsigned long flags; spin_lock_irqsave(&input_device_ids_lock, &flags); @@ -69,13 +69,17 @@ kern_status_t input_device_register(struct input_device *dev) bitmap_set(input_device_ids, id); spin_unlock_irqrestore(&input_device_ids_lock, flags); - dev->i_id = id; + struct input_device *inputdev = &dev->input; + inputdev->i_id = id; char name[DEV_NAME_MAX]; - generate_name(dev, name); + generate_name(inputdev, name); char path[OBJECT_PATH_MAX]; snprintf(path, sizeof path, "/dev/input/%s", name); - struct device *base = input_device_base(dev); - return object_namespace_create_link(global_namespace(), path, &base->dev_base); + return object_namespace_create_link(global_namespace(), path, &dev->dev_base); } + +struct device_type_ops input_type_ops = { + .register_device = input_device_register, +}; diff --git a/include/socks/device.h b/include/socks/device.h index 02de1bc..059e632 100644 --- a/include/socks/device.h +++ b/include/socks/device.h @@ -6,6 +6,7 @@ #include #include #include +#include #include struct device; @@ -19,12 +20,14 @@ struct input_event; #define INPUT_DEVICE_EVENT_QUEUE_SIZE 128 #define INPUT_DEVICE_MAX 4096 +#define FRAMEBUFFER_DEVICE_MAX 4096 #define BLOCK_DEVICE(dev) ((dev)->dev_type == DEV_TYPE_BLOCK ? &(dev)->blk : NULL) #define CHAR_DEVICE(dev) ((dev)->dev_type == DEV_TYPE_CHAR ? &(dev)->chr : NULL) #define NET_DEVICE(dev) ((dev)->dev_type == DEV_TYPE_NET ? &(dev)->net : NULL) #define INPUT_DEVICE(dev) ((dev)->dev_type == DEV_TYPE_INPUT ? &(dev)->input : NULL) #define BUS_DEVICE(dev) ((dev)->dev_type == DEV_TYPE_BUS ? &(dev)->bus : NULL) +#define FRAMEBUFFER_DEVICE(dev) ((dev)->dev_type == DEV_TYPE_FRAMEBUFFER ? &(dev)->fb : NULL) enum device_type { DEV_TYPE_UNKNOWN = 0, @@ -33,6 +36,11 @@ enum device_type { DEV_TYPE_NET, DEV_TYPE_INPUT, DEV_TYPE_BUS, + DEV_TYPE_FRAMEBUFFER, +}; + +struct device_type_ops { + kern_status_t(*register_device)(struct device *); }; struct block_device_ops { @@ -61,6 +69,10 @@ struct bus_device_ops { kern_status_t(*scan)(struct device *); }; +struct framebuffer_device_ops { + kern_status_t(*scan)(struct device *); +}; + struct block_device { struct block_device_ops *b_ops; }; @@ -83,6 +95,13 @@ struct bus_device { struct bus_device_ops *b_ops; }; +struct framebuffer_device { + unsigned int fb_id; + struct framebuffer_device_ops *fb_ops; + struct framebuffer_varinfo fb_varinfo; + struct framebuffer_fixedinfo fb_fixedinfo; +}; + struct device { struct object dev_base; unsigned int dev_minor; @@ -103,6 +122,7 @@ struct device { struct net_device net; struct input_device input; struct bus_device bus; + struct framebuffer_device fb; }; }; @@ -160,6 +180,7 @@ extern struct block_device *block_device_create(void); extern struct net_device *net_device_create(void); extern struct input_device *input_device_create(void); extern struct bus_device *bus_device_create(void); +extern struct framebuffer_device *framebuffer_device_create(void); static inline struct device *char_device_base(struct char_device *dev) { @@ -186,11 +207,15 @@ static inline struct device *bus_device_base(struct bus_device *dev) return (struct device *)((char *)dev - offsetof(struct device, bus)); } +static inline struct device *framebuffer_device_base(struct framebuffer_device *dev) +{ + return (struct device *)((char *)dev - offsetof(struct device, fb)); +} + extern kern_status_t device_register(struct device *dev, struct driver *owner, struct device *parent); extern kern_status_t input_device_report_event(struct input_device *dev, const struct input_event *ev, bool noblock); extern kern_status_t input_device_read(struct device *dev, void *buf, size_t size, size_t *bytes_read, socks_flags_t flags); -extern kern_status_t input_device_register(struct input_device *dev); extern struct driver *driver_create(struct kext *self, const char *name); extern kern_status_t driver_destroy(struct driver *driver); diff --git a/include/socks/fb.h b/include/socks/fb.h new file mode 100644 index 0000000..73f13c9 --- /dev/null +++ b/include/socks/fb.h @@ -0,0 +1,33 @@ +#ifndef SOCKS_FB_H_ +#define SOCKS_FB_H_ + +#include + +enum framebuffer_flags { + FB_VGATEXT = 0x01u, +}; + +struct framebuffer_bitfield { + uint32_t b_offset; + uint16_t b_length; +}; + +struct framebuffer_varinfo { + enum framebuffer_flags fb_flags; + + uint32_t fb_xres; + uint32_t fb_yres; + 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; +}; + +struct framebuffer_fixedinfo { + uint64_t fb_baseptr; +}; + +#endif diff --git a/kexts/drivers/video/vgafb/extension.yaml b/kexts/drivers/video/vgafb/extension.yaml new file mode 100644 index 0000000..e830555 --- /dev/null +++ b/kexts/drivers/video/vgafb/extension.yaml @@ -0,0 +1,8 @@ +name: vgafb +description: | + Generic VGA driver. +id: net.doorstuck.socks.vgafb +license: BSD-3-Clause +copyright: Copyright © Max Wash 2023 +sources: + - main.c diff --git a/kexts/drivers/video/vgafb/main.c b/kexts/drivers/video/vgafb/main.c new file mode 100644 index 0000000..29aad7f --- /dev/null +++ b/kexts/drivers/video/vgafb/main.c @@ -0,0 +1,36 @@ +#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);