From 739dfa233fb3b4379c67271ddb72f0f3400d4a22 Mon Sep 17 00:00:00 2001 From: Yuta Imazu Date: Sun, 16 Jun 2024 23:45:02 +0900 Subject: [PATCH] kernel+userland: refactor initialization --- kernel/Makefile | 20 ++-- kernel/console/console.c | 11 +++ kernel/console/console.h | 10 +- kernel/console/fb_console.c | 75 +++++++-------- kernel/console/serial_console.c | 24 +++-- kernel/console/system_console.c | 29 ++++-- kernel/{ => drivers}/ac97.c | 91 ++++++++++--------- kernel/drivers/drivers.c | 16 ++++ kernel/drivers/drivers.h | 5 + kernel/{ => drivers}/graphics/bochs.c | 2 +- kernel/{ => drivers}/graphics/fb.c | 39 ++++---- .../graphics/graphics.h} | 4 +- kernel/{ => drivers}/graphics/multiboot.c | 2 +- kernel/{ => drivers}/hid/hid.h | 4 - kernel/{ => drivers}/hid/keyboard.c | 14 +-- kernel/{ => drivers}/hid/mouse.c | 18 ++-- kernel/{ => drivers}/hid/ps2.c | 6 +- kernel/{ => drivers}/pseudo_device.c | 29 ++++-- kernel/{ => drivers/serial}/serial.c | 34 +++++-- kernel/{ => drivers/serial}/serial.h | 6 +- kernel/forward.h | 1 + kernel/fs/fs.h | 10 +- kernel/fs/vfs.c | 43 ++++++--- kernel/graphics/graphics.h | 15 --- kernel/kprintf.c | 2 +- kernel/main.c | 80 +++------------- kernel/system.c | 2 +- kernel/system.h | 10 -- userland/init.c | 54 ++++++++--- 29 files changed, 350 insertions(+), 306 deletions(-) create mode 100644 kernel/console/console.c rename kernel/{ => drivers}/ac97.c (94%) create mode 100644 kernel/drivers/drivers.c create mode 100644 kernel/drivers/drivers.h rename kernel/{ => drivers}/graphics/bochs.c (99%) rename kernel/{ => drivers}/graphics/fb.c (68%) rename kernel/{graphics/fb_private.h => drivers/graphics/graphics.h} (70%) rename kernel/{ => drivers}/graphics/multiboot.c (98%) rename kernel/{ => drivers}/hid/hid.h (86%) rename kernel/{ => drivers}/hid/keyboard.c (98%) rename kernel/{ => drivers}/hid/mouse.c (96%) rename kernel/{ => drivers}/hid/ps2.c (94%) rename kernel/{ => drivers}/pseudo_device.c (77%) rename kernel/{ => drivers/serial}/serial.c (74%) rename kernel/{ => drivers/serial}/serial.h (85%) delete mode 100644 kernel/graphics/graphics.h diff --git a/kernel/Makefile b/kernel/Makefile index 1e0fd7ee..edd82622 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -3,14 +3,24 @@ CFLAGS += -isystem.. TARGET := kernel OBJS := \ - ac97.o \ boot.o \ cmdline.o \ + console/console.o \ console/fb_console.o \ console/psf.o \ console/serial_console.o \ console/system_console.o \ console/tty.o \ + drivers/ac97.o \ + drivers/drivers.o \ + drivers/graphics/bochs.o \ + drivers/graphics/fb.o \ + drivers/graphics/multiboot.o \ + drivers/hid/keyboard.o \ + drivers/hid/mouse.o \ + drivers/hid/ps2.o \ + drivers/pseudo_device.o \ + drivers/serial/serial.o \ exec.o \ fs/dentry.o \ fs/fifo.o \ @@ -22,13 +32,7 @@ OBJS := \ fs/tmpfs.o \ fs/vfs.o \ gdt.o \ - graphics/bochs.o \ - graphics/fb.o \ - graphics/multiboot.o \ growable_buf.o \ - hid/keyboard.o \ - hid/mouse.o \ - hid/ps2.o \ idt.o \ interrupt.o \ irq.o \ @@ -42,12 +46,10 @@ OBJS := \ pci.o \ pit.o \ process.o \ - pseudo_device.o \ random.o \ ring_buf.o \ safe_string.o \ scheduler.o \ - serial.o \ syscall/clock.o \ syscall/fs.o \ syscall/mmap.o \ diff --git a/kernel/console/console.c b/kernel/console/console.c new file mode 100644 index 00000000..967619cf --- /dev/null +++ b/kernel/console/console.c @@ -0,0 +1,11 @@ +#include "console.h" + +void serial_console_init(void); +void fb_console_init(void); +void system_console_init(void); + +void console_init(void) { + serial_console_init(); + fb_console_init(); + system_console_init(); +} diff --git a/kernel/console/console.h b/kernel/console/console.h index 9d46df06..5594297a 100644 --- a/kernel/console/console.h +++ b/kernel/console/console.h @@ -1,17 +1,9 @@ #pragma once -#include #include -#include -void fb_console_init(void); -struct inode* fb_console_device_get(void); +void console_init(void); -void serial_console_init(void); void serial_console_on_char(uint16_t port, char); -struct inode* serial_console_device_create(uint16_t port); - -void system_console_init(void); -struct inode* system_console_device_get(void); void tty_maybe_send_signal(pid_t pgid, char ch); diff --git a/kernel/console/fb_console.c b/kernel/console/fb_console.c index 52541a6f..0d794b3f 100644 --- a/kernel/console/fb_console.c +++ b/kernel/console/fb_console.c @@ -11,8 +11,9 @@ #include #include #include -#include -#include +#include +#include +#include #include #include #include @@ -490,39 +491,6 @@ static void on_key_event(const key_event* event) { pop_cli(int_flag); } -static bool initialized = false; -static mutex lock; - -void fb_console_init(void) { - font = load_psf("/usr/share/fonts/ter-u16n.psf"); - ASSERT_OK(font); - - ASSERT_OK(fb_get_info(&fb_info)); - ASSERT(fb_info.bpp == 32); - - num_columns = fb_info.width / font->glyph_width; - num_rows = fb_info.height / font->glyph_height; - - cells = kmalloc(num_columns * num_rows * sizeof(struct cell)); - ASSERT(cells); - line_is_dirty = kmalloc(num_rows * sizeof(bool)); - ASSERT(line_is_dirty); - - size_t fb_size = fb_info.pitch * fb_info.height; - fb_addr = range_allocator_alloc(&kernel_vaddr_allocator, fb_size); - ASSERT_OK(fb_addr); - ASSERT_OK( - fb_mmap(fb_addr, fb_size, 0, PAGE_WRITE | PAGE_SHARED | PAGE_GLOBAL)); - - clear_screen(); - flush(); - - ASSERT_OK(ring_buf_init(&input_buf)); - ps2_set_key_event_handler(on_key_event); - - initialized = true; -} - static bool can_read(void) { bool int_flag = push_cli(); bool ret = !ring_buf_is_empty(&input_buf); @@ -556,6 +524,8 @@ static ssize_t fb_console_device_read(file_description* desc, void* buffer, } } +static mutex lock; + static ssize_t fb_console_device_write(file_description* desc, const void* buffer, size_t count) { (void)desc; @@ -610,7 +580,7 @@ static short fb_console_device_poll(file_description* desc, short events) { return revents; } -struct inode* fb_console_device_get(void) { +static struct inode* fb_console_device_get(void) { static file_ops fops = {.read = fb_console_device_read, .write = fb_console_device_write, .ioctl = fb_console_device_ioctl, @@ -621,3 +591,36 @@ struct inode* fb_console_device_get(void) { .ref_count = 1}; return &inode; } + +void fb_console_init(void) { + if (!fb_get()) + return; + + font = load_psf("/usr/share/fonts/ter-u16n.psf"); + ASSERT_OK(font); + + ASSERT_OK(fb_get()->get_info(&fb_info)); + ASSERT(fb_info.bpp == 32); + + num_columns = fb_info.width / font->glyph_width; + num_rows = fb_info.height / font->glyph_height; + + cells = kmalloc(num_columns * num_rows * sizeof(struct cell)); + ASSERT(cells); + line_is_dirty = kmalloc(num_rows * sizeof(bool)); + ASSERT(line_is_dirty); + + size_t fb_size = fb_info.pitch * fb_info.height; + fb_addr = range_allocator_alloc(&kernel_vaddr_allocator, fb_size); + ASSERT_OK(fb_addr); + ASSERT_OK(fb_get()->mmap(fb_addr, fb_size, 0, + PAGE_WRITE | PAGE_SHARED | PAGE_GLOBAL)); + + clear_screen(); + flush(); + + ASSERT_OK(ring_buf_init(&input_buf)); + ps2_set_key_event_handler(on_key_event); + + ASSERT_OK(vfs_register_device(fb_console_device_get())); +} diff --git a/kernel/console/serial_console.c b/kernel/console/serial_console.c index 3d77133f..173a1a81 100644 --- a/kernel/console/serial_console.c +++ b/kernel/console/serial_console.c @@ -3,22 +3,17 @@ #include #include #include +#include #include #include #include #include #include #include -#include static ring_buf input_bufs[4]; static pid_t pgid; -void serial_console_init(void) { - for (size_t i = 0; i < 4; ++i) - ASSERT_OK(ring_buf_init(input_bufs + i)); -} - static ring_buf* get_input_buf_for_port(uint16_t port) { uint8_t com_number = serial_port_to_com_number(port); if (com_number) @@ -111,7 +106,7 @@ static short serial_console_device_poll(file_description* desc, short events) { return revents; } -struct inode* serial_console_device_create(uint16_t port) { +static struct inode* serial_console_device_create(uint16_t port) { if (!serial_is_valid_port(port)) return NULL; @@ -134,3 +129,18 @@ struct inode* serial_console_device_create(uint16_t port) { return inode; } + +void serial_console_init(void) { + for (size_t i = 0; i < 4; ++i) + ASSERT_OK(ring_buf_init(input_bufs + i)); + + const uint16_t ports[] = {SERIAL_COM1, SERIAL_COM2, SERIAL_COM3, + SERIAL_COM4}; + for (size_t i = 0; i < ARRAY_SIZE(ports); ++i) { + if (serial_is_port_enabled(ports[i])) { + struct inode* device = serial_console_device_create(ports[i]); + ASSERT_OK(device); + ASSERT_OK(vfs_register_device(device)); + } + } +} diff --git a/kernel/console/system_console.c b/kernel/console/system_console.c index 7c552a92..db83bc80 100644 --- a/kernel/console/system_console.c +++ b/kernel/console/system_console.c @@ -5,20 +5,20 @@ #include #include -static file_description* active_console = NULL; - -void system_console_init(void) { - active_console = vfs_open("/dev/tty", O_RDWR, 0); - if (IS_OK(active_console)) - return; +static struct inode* get_tty_device(void) { + struct inode* device = vfs_get_device(makedev(5, 0)); // /dev/tty + if (device) + return device; - active_console = vfs_open("/dev/ttyS0", O_RDWR, 0); - if (IS_OK(active_console)) - return; + device = vfs_get_device(makedev(4, 64)); // /dev/ttyS0 + if (device) + return device; - UNIMPLEMENTED(); + return NULL; } +static file_description* active_console = NULL; + static ssize_t system_console_device_read(file_description* desc, void* buffer, size_t count) { (void)desc; @@ -49,3 +49,12 @@ struct inode* system_console_device_get(void) { .ref_count = 1}; return &inode; } + +void system_console_init(void) { + struct inode* device = get_tty_device(); + ASSERT_OK(device); + active_console = inode_open(device, O_RDWR, 0); + ASSERT_OK(active_console); + + ASSERT_OK(vfs_register_device(system_console_device_get())); +} diff --git a/kernel/ac97.c b/kernel/drivers/ac97.c similarity index 94% rename from kernel/ac97.c rename to kernel/drivers/ac97.c index 95eb138a..9245f38a 100644 --- a/kernel/ac97.c +++ b/kernel/drivers/ac97.c @@ -1,14 +1,15 @@ -#include "api/err.h" -#include "api/sound.h" -#include "api/sys/poll.h" -#include "api/sys/sysmacros.h" -#include "boot_defs.h" -#include "fs/fs.h" -#include "interrupts.h" -#include "memory/memory.h" -#include "pci.h" -#include "safe_string.h" -#include "system.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include #define PCI_CLASS_MULTIMEDIA 4 @@ -83,39 +84,6 @@ static void irq_handler(registers* regs) { buffer_descriptor_list_is_full = false; } -bool ac97_init(void) { - pci_enumerate(pci_enumeration_callback); - if (!device_detected) - return false; - - pci_set_interrupt_line_enabled(&device_addr, true); - pci_set_bus_mastering_enabled(&device_addr, true); - - uint32_t control = in32(bus_base + BUS_GLOBAL_CONTROL); - control |= GLOBAL_CONTROL_GLOBAL_INTERRUPT_ENABLE; - control |= GLOBAL_CONTROL_COLD_RESET; - out32(bus_base + BUS_GLOBAL_CONTROL, control); - - out16(mixer_base + MIXER_RESET_REGISTER, 1); - - out16(mixer_base + MIXER_SAMPLE_RATE, 48000); - - // zero attenuation i.e. full volume - out16(mixer_base + MIXER_MASTER_OUTPUT_VOLUME, 0); - out16(mixer_base + MIXER_PCM_OUTPUT_VOLUME, 0); - - pcm_out_channel = bus_base + BUS_PCM_OUT; - out8(pcm_out_channel + CHANNEL_TRANSFTER_CONTROL, TRANSFER_CONTROL_RESET); - while (in8(pcm_out_channel + CHANNEL_TRANSFTER_CONTROL) & - TRANSFER_CONTROL_RESET) - delay(50); - - uint8_t irq_num = pci_get_interrupt_line(&device_addr); - idt_set_interrupt_handler(IRQ(irq_num), irq_handler); - - return true; -} - #define OUTPUT_BUF_NUM_PAGES 4 alignas(PAGE_SIZE) static unsigned char output_buf[OUTPUT_BUF_NUM_PAGES * @@ -273,7 +241,7 @@ static short ac97_device_poll(file_description* desc, short events) { return revents; } -struct inode* ac97_device_get(void) { +static struct inode* ac97_device_get(void) { static file_ops fops = {.write = ac97_device_write, .ioctl = ac97_device_ioctl, .poll = ac97_device_poll}; @@ -283,3 +251,36 @@ struct inode* ac97_device_get(void) { .ref_count = 1}; return &inode; } + +void ac97_init(void) { + pci_enumerate(pci_enumeration_callback); + if (!device_detected) + return; + + pci_set_interrupt_line_enabled(&device_addr, true); + pci_set_bus_mastering_enabled(&device_addr, true); + + uint32_t control = in32(bus_base + BUS_GLOBAL_CONTROL); + control |= GLOBAL_CONTROL_GLOBAL_INTERRUPT_ENABLE; + control |= GLOBAL_CONTROL_COLD_RESET; + out32(bus_base + BUS_GLOBAL_CONTROL, control); + + out16(mixer_base + MIXER_RESET_REGISTER, 1); + + out16(mixer_base + MIXER_SAMPLE_RATE, 48000); + + // zero attenuation i.e. full volume + out16(mixer_base + MIXER_MASTER_OUTPUT_VOLUME, 0); + out16(mixer_base + MIXER_PCM_OUTPUT_VOLUME, 0); + + pcm_out_channel = bus_base + BUS_PCM_OUT; + out8(pcm_out_channel + CHANNEL_TRANSFTER_CONTROL, TRANSFER_CONTROL_RESET); + while (in8(pcm_out_channel + CHANNEL_TRANSFTER_CONTROL) & + TRANSFER_CONTROL_RESET) + delay(50); + + uint8_t irq_num = pci_get_interrupt_line(&device_addr); + idt_set_interrupt_handler(IRQ(irq_num), irq_handler); + + ASSERT_OK(vfs_register_device(ac97_device_get())); +} diff --git a/kernel/drivers/drivers.c b/kernel/drivers/drivers.c new file mode 100644 index 00000000..3f2eefea --- /dev/null +++ b/kernel/drivers/drivers.c @@ -0,0 +1,16 @@ +#include "drivers.h" +#include + +void pseudo_device_init(void); +void serial_late_init(void); +void ps2_init(void); +void fb_init(const multiboot_info_t*); +void ac97_init(void); + +void drivers_init(const multiboot_info_t* mb_info) { + pseudo_device_init(); + serial_late_init(); + ps2_init(); + fb_init(mb_info); + ac97_init(); +} diff --git a/kernel/drivers/drivers.h b/kernel/drivers/drivers.h new file mode 100644 index 00000000..d9ee99ca --- /dev/null +++ b/kernel/drivers/drivers.h @@ -0,0 +1,5 @@ +#pragma once + +#include + +void drivers_init(const multiboot_info_t*); diff --git a/kernel/graphics/bochs.c b/kernel/drivers/graphics/bochs.c similarity index 99% rename from kernel/graphics/bochs.c rename to kernel/drivers/graphics/bochs.c index e860eebd..70043beb 100644 --- a/kernel/graphics/bochs.c +++ b/kernel/drivers/graphics/bochs.c @@ -1,4 +1,4 @@ -#include "fb_private.h" +#include "graphics.h" #include #include #include diff --git a/kernel/graphics/fb.c b/kernel/drivers/graphics/fb.c similarity index 68% rename from kernel/graphics/fb.c rename to kernel/drivers/graphics/fb.c index 3754621e..1efa5a67 100644 --- a/kernel/graphics/fb.c +++ b/kernel/drivers/graphics/fb.c @@ -1,34 +1,28 @@ -#include "fb_private.h" #include "graphics.h" -#include #include #include #include +#include #include -#include static struct fb* fb; -bool fb_init(const multiboot_info_t* mb_info) { - fb = bochs_fb_init(); +struct fb* bochs_fb_init(void); +struct fb* multiboot_fb_init(const multiboot_info_t*); + +static struct fb* find_fb(const multiboot_info_t* mb_info) { + struct fb* fb = bochs_fb_init(); if (fb) - return true; - fb = multiboot_fb_init(mb_info); - return fb; + return fb; + return multiboot_fb_init(mb_info); } -int fb_get_info(struct fb_info* out_info) { return fb->get_info(out_info); } - -int fb_set_info(struct fb_info* inout_info) { return fb->set_info(inout_info); } - -int fb_mmap(uintptr_t addr, size_t length, off_t offset, uint16_t page_flags) { - return fb->mmap(addr, length, offset, page_flags); -} +struct fb* fb_get(void) { return fb; } static int fb_device_mmap(file_description* desc, uintptr_t addr, size_t length, off_t offset, uint16_t page_flags) { (void)desc; - return fb_mmap(addr, length, offset, page_flags); + return fb->mmap(addr, length, offset, page_flags); } static int fb_device_ioctl(file_description* desc, int request, @@ -38,7 +32,7 @@ static int fb_device_ioctl(file_description* desc, int request, struct fb_info info; switch (request) { case FBIOGET_INFO: { - int rc = fb_get_info(&info); + int rc = fb->get_info(&info); if (IS_ERR(rc)) return rc; break; @@ -46,7 +40,7 @@ static int fb_device_ioctl(file_description* desc, int request, case FBIOSET_INFO: { if (!copy_from_user(&info, user_argp, sizeof(struct fb_info))) return -EFAULT; - int rc = fb_set_info(&info); + int rc = fb->set_info(&info); if (IS_ERR(rc)) return rc; break; @@ -60,7 +54,7 @@ static int fb_device_ioctl(file_description* desc, int request, return 0; } -struct inode* fb_device_get(void) { +static struct inode* fb_device_get(void) { static file_ops fops = {.mmap = fb_device_mmap, .ioctl = fb_device_ioctl}; static struct inode inode = {.fops = &fops, .mode = S_IFBLK, @@ -68,3 +62,10 @@ struct inode* fb_device_get(void) { .ref_count = 1}; return &inode; } + +void fb_init(const multiboot_info_t* mb_info) { + fb = find_fb(mb_info); + if (!fb) + return; + ASSERT_OK(vfs_register_device(fb_device_get())); +} diff --git a/kernel/graphics/fb_private.h b/kernel/drivers/graphics/graphics.h similarity index 70% rename from kernel/graphics/fb_private.h rename to kernel/drivers/graphics/graphics.h index 3c27eaa2..3b808ea4 100644 --- a/kernel/graphics/fb_private.h +++ b/kernel/drivers/graphics/graphics.h @@ -2,7 +2,6 @@ #include #include -#include struct fb { int (*get_info)(struct fb_info* out_info); @@ -11,5 +10,4 @@ struct fb { uint16_t page_flags); }; -struct fb* bochs_fb_init(void); -struct fb* multiboot_fb_init(const multiboot_info_t* mb_info); +struct fb* fb_get(void); diff --git a/kernel/graphics/multiboot.c b/kernel/drivers/graphics/multiboot.c similarity index 98% rename from kernel/graphics/multiboot.c rename to kernel/drivers/graphics/multiboot.c index 4dc0ea73..d64de309 100644 --- a/kernel/graphics/multiboot.c +++ b/kernel/drivers/graphics/multiboot.c @@ -1,4 +1,4 @@ -#include "fb_private.h" +#include "graphics.h" #include #include #include diff --git a/kernel/hid/hid.h b/kernel/drivers/hid/hid.h similarity index 86% rename from kernel/hid/hid.h rename to kernel/drivers/hid/hid.h index ffc1b5e3..015ed5fa 100644 --- a/kernel/hid/hid.h +++ b/kernel/drivers/hid/hid.h @@ -1,6 +1,5 @@ #pragma once -#include #include #include @@ -39,7 +38,4 @@ static inline void ps2_write(uint8_t port, uint8_t data) { typedef void (*ps2_key_event_handler_fn)(const key_event*); -NODISCARD bool ps2_init(void); void ps2_set_key_event_handler(ps2_key_event_handler_fn); -struct inode* ps2_keyboard_device_get(void); -struct inode* ps2_mouse_device_get(void); diff --git a/kernel/hid/keyboard.c b/kernel/drivers/hid/keyboard.c similarity index 98% rename from kernel/hid/keyboard.c rename to kernel/drivers/hid/keyboard.c index f1e0d20b..fd0c83de 100644 --- a/kernel/hid/keyboard.c +++ b/kernel/drivers/hid/keyboard.c @@ -316,11 +316,6 @@ static void irq_handler(registers* reg) { event_handler(event); } -void ps2_keyboard_init(void) { - ps2_write(PS2_COMMAND, PS2_ENABLE_PORT1); - idt_set_interrupt_handler(IRQ(1), irq_handler); -} - void ps2_set_key_event_handler(ps2_key_event_handler_fn handler) { event_handler = handler; } @@ -377,7 +372,7 @@ static short ps2_keyboard_device_poll(file_description* desc, short events) { return revents; } -struct inode* ps2_keyboard_device_get(void) { +static struct inode* ps2_keyboard_device_get(void) { static file_ops fops = {.read = ps2_keyboard_device_read, .poll = ps2_keyboard_device_poll}; static struct inode inode = {.fops = &fops, @@ -386,3 +381,10 @@ struct inode* ps2_keyboard_device_get(void) { .ref_count = 1}; return &inode; } + +void ps2_keyboard_init(void) { + ps2_write(PS2_COMMAND, PS2_ENABLE_PORT1); + idt_set_interrupt_handler(IRQ(1), irq_handler); + + ASSERT_OK(vfs_register_device(ps2_keyboard_device_get())); +} diff --git a/kernel/hid/mouse.c b/kernel/drivers/hid/mouse.c similarity index 96% rename from kernel/hid/mouse.c rename to kernel/drivers/hid/mouse.c index 693d578e..2ca180cf 100644 --- a/kernel/hid/mouse.c +++ b/kernel/drivers/hid/mouse.c @@ -56,13 +56,6 @@ static void irq_handler(registers* reg) { UNREACHABLE(); } -void ps2_mouse_init(void) { - ps2_write(PS2_COMMAND, PS2_ENABLE_PORT2); - write_mouse(PS2_MOUSE_SET_DEFAULTS); - write_mouse(PS2_MOUSE_ENABLE_PACKET_STREAMING); - idt_set_interrupt_handler(IRQ(12), irq_handler); -} - static bool can_read(void) { bool int_flag = push_cli(); bool ret = queue_read_idx != queue_write_idx; @@ -116,7 +109,7 @@ static short ps2_mouse_device_poll(file_description* desc, short events) { return revents; } -struct inode* ps2_mouse_device_get(void) { +static struct inode* ps2_mouse_device_get(void) { static file_ops fops = {.read = ps2_mouse_device_read, .poll = ps2_mouse_device_poll}; static struct inode inode = {.fops = &fops, @@ -125,3 +118,12 @@ struct inode* ps2_mouse_device_get(void) { .ref_count = 1}; return &inode; } + +void ps2_mouse_init(void) { + ps2_write(PS2_COMMAND, PS2_ENABLE_PORT2); + write_mouse(PS2_MOUSE_SET_DEFAULTS); + write_mouse(PS2_MOUSE_ENABLE_PACKET_STREAMING); + idt_set_interrupt_handler(IRQ(12), irq_handler); + + ASSERT_OK(vfs_register_device(ps2_mouse_device_get())); +} diff --git a/kernel/hid/ps2.c b/kernel/drivers/hid/ps2.c similarity index 94% rename from kernel/hid/ps2.c rename to kernel/drivers/hid/ps2.c index a4343fc4..b8f3331d 100644 --- a/kernel/hid/ps2.c +++ b/kernel/drivers/hid/ps2.c @@ -20,10 +20,10 @@ static bool self_test(void) { return false; } -bool ps2_init(void) { +void ps2_init(void) { drain_output_buffer(); if (!self_test()) - return false; + return; ps2_write(PS2_COMMAND, PS2_DISABLE_PORT1); ps2_write(PS2_COMMAND, PS2_DISABLE_PORT2); @@ -41,6 +41,4 @@ bool ps2_init(void) { drain_output_buffer(); ps2_mouse_init(); - - return true; } diff --git a/kernel/pseudo_device.c b/kernel/drivers/pseudo_device.c similarity index 77% rename from kernel/pseudo_device.c rename to kernel/drivers/pseudo_device.c index 844faad6..d08199f1 100644 --- a/kernel/pseudo_device.c +++ b/kernel/drivers/pseudo_device.c @@ -1,8 +1,9 @@ -#include "api/err.h" -#include "api/sys/sysmacros.h" -#include "fs/fs.h" -#include "memory/memory.h" -#include "system.h" +#include +#include +#include +#include +#include +#include #include static ssize_t read_nothing(file_description* desc, void* buffer, @@ -40,7 +41,7 @@ static ssize_t write_to_full_disk(file_description* desc, const void* buffer, return 0; } -struct inode* null_device_get(void) { +static struct inode* null_device_get(void) { static file_ops fops = {.read = read_nothing, .write = write_to_bit_bucket}; static struct inode inode = {.fops = &fops, .mode = S_IFCHR, @@ -49,7 +50,7 @@ struct inode* null_device_get(void) { return &inode; } -struct inode* zero_device_get(void) { +static struct inode* zero_device_get(void) { static file_ops fops = {.read = read_zeros, .write = write_to_bit_bucket}; static struct inode inode = {.fops = &fops, .mode = S_IFCHR, @@ -58,7 +59,7 @@ struct inode* zero_device_get(void) { return &inode; } -struct inode* full_device_get(void) { +static struct inode* full_device_get(void) { static file_ops fops = {.read = read_zeros, .write = write_to_full_disk}; static struct inode inode = {.fops = &fops, .mode = S_IFCHR, @@ -67,7 +68,7 @@ struct inode* full_device_get(void) { return &inode; } -struct inode* random_device_get(void) { +static struct inode* random_device_get(void) { static file_ops fops = {.read = read_random, .write = write_to_bit_bucket}; static struct inode inode = {.fops = &fops, .mode = S_IFCHR, @@ -76,7 +77,7 @@ struct inode* random_device_get(void) { return &inode; } -struct inode* urandom_device_get(void) { +static struct inode* urandom_device_get(void) { static file_ops fops = {.read = read_random, .write = write_to_bit_bucket}; static struct inode inode = {.fops = &fops, .mode = S_IFCHR, @@ -84,3 +85,11 @@ struct inode* urandom_device_get(void) { .ref_count = 1}; return &inode; } + +void pseudo_device_init(void) { + ASSERT_OK(vfs_register_device(null_device_get())); + ASSERT_OK(vfs_register_device(zero_device_get())); + ASSERT_OK(vfs_register_device(full_device_get())); + ASSERT_OK(vfs_register_device(random_device_get())); + ASSERT_OK(vfs_register_device(urandom_device_get())); +} diff --git a/kernel/serial.c b/kernel/drivers/serial/serial.c similarity index 74% rename from kernel/serial.c rename to kernel/drivers/serial/serial.c index 932c77cd..3d44ff8a 100644 --- a/kernel/serial.c +++ b/kernel/drivers/serial/serial.c @@ -1,7 +1,8 @@ #include "serial.h" -#include "console/console.h" -#include "interrupts.h" -#include "panic.h" +#include +#include +#include +#include static void init_port(uint16_t port) { out8(port + 1, 0x00); @@ -13,7 +14,7 @@ static void init_port(uint16_t port) { out8(port + 4, 0x0b); } -void serial_init(void) { init_port(SERIAL_COM1); } +void serial_early_init(void) { init_port(SERIAL_COM1); } #define DATA_READY 0x1 #define TRANSMITTER_HOLDING_REGISTER_EMPTY 0x20 @@ -39,7 +40,9 @@ static void handle_2_and_4(registers* regs) { ; } -bool serial_enable_port(uint16_t port) { +static bool is_port_enabled[4]; + +static bool enable_port(uint16_t port) { if (!serial_is_valid_port(port)) return false; @@ -58,13 +61,28 @@ bool serial_enable_port(uint16_t port) { case SERIAL_COM1: case SERIAL_COM3: idt_set_interrupt_handler(IRQ(4), handle_1_and_3); - return true; + break; case SERIAL_COM2: case SERIAL_COM4: idt_set_interrupt_handler(IRQ(3), handle_2_and_4); - return true; + break; + default: + UNREACHABLE(); } - UNREACHABLE(); + + is_port_enabled[serial_port_to_com_number(port) - 1] = true; + return true; +} + +bool serial_is_port_enabled(uint16_t port) { + return is_port_enabled[serial_port_to_com_number(port) - 1]; +} + +void serial_late_init(void) { + enable_port(SERIAL_COM1); + enable_port(SERIAL_COM2); + enable_port(SERIAL_COM3); + enable_port(SERIAL_COM4); } static void write_char(uint16_t port, char c) { diff --git a/kernel/serial.h b/kernel/drivers/serial/serial.h similarity index 85% rename from kernel/serial.h rename to kernel/drivers/serial/serial.h index faaac112..31bb7115 100644 --- a/kernel/serial.h +++ b/kernel/drivers/serial/serial.h @@ -1,7 +1,5 @@ #pragma once -#include "forward.h" -#include #include #include #include @@ -11,8 +9,8 @@ #define SERIAL_COM3 0x3e8 #define SERIAL_COM4 0x2e8 -void serial_init(void); -NODISCARD bool serial_enable_port(uint16_t port); +void serial_early_init(void); +bool serial_is_port_enabled(uint16_t port); size_t serial_write(uint16_t port, const char* s, size_t count); static inline bool serial_is_valid_port(uint16_t port) { diff --git a/kernel/forward.h b/kernel/forward.h index 7bbfb0b5..9d0954e2 100644 --- a/kernel/forward.h +++ b/kernel/forward.h @@ -2,6 +2,7 @@ // multiboot.h typedef struct multiboot_info multiboot_info_t; +typedef struct multiboot_mod_list multiboot_module_t; // system.h typedef struct registers registers; diff --git a/kernel/fs/fs.h b/kernel/fs/fs.h index e1dcbe07..89f1cac0 100644 --- a/kernel/fs/fs.h +++ b/kernel/fs/fs.h @@ -100,13 +100,19 @@ NODISCARD int file_description_getdents(file_description*, getdents_callback_fn, NODISCARD int file_description_block(file_description*, bool (*should_unblock)(file_description*)); -NODISCARD int vfs_mount(const char* path, struct inode* fs_root); +void vfs_init(void); +void vfs_populate_root_fs(const multiboot_module_t* initrd_mod); struct inode* vfs_get_root(void); +NODISCARD int vfs_mount(const char* path, struct inode* fs_root); + NODISCARD int vfs_register_device(struct inode* device); +struct inode* vfs_get_device(dev_t); + NODISCARD file_description* vfs_open(const char* pathname, int flags, mode_t mode); NODISCARD int vfs_stat(const char* pathname, struct stat* buf); NODISCARD struct inode* vfs_create(const char* pathname, mode_t mode); + char* vfs_canonicalize_path(const char* pathname); struct inode* vfs_resolve_path(const char* pathname, struct inode** out_parent, char** out_basename); @@ -115,7 +121,5 @@ uint8_t mode_to_dirent_type(mode_t); struct inode* fifo_create(void); -void initrd_populate_root_fs(uintptr_t physical_addr, size_t size); - struct inode* tmpfs_create_root(void); struct inode* procfs_create_root(void); diff --git a/kernel/fs/vfs.c b/kernel/fs/vfs.c index e3510a8d..70068829 100644 --- a/kernel/fs/vfs.c +++ b/kernel/fs/vfs.c @@ -5,25 +5,37 @@ #include #include #include +#include #include #include #include +void initrd_populate_root_fs(uintptr_t paddr, size_t size); + +static struct inode* root; + +void vfs_init(void) { ASSERT_OK(vfs_mount(ROOT_DIR, tmpfs_create_root())); } + +void vfs_populate_root_fs(const multiboot_module_t* initrd_mod) { + uintptr_t initrd_paddr = initrd_mod->mod_start; + uintptr_t initrd_size = initrd_mod->mod_end - initrd_mod->mod_start; + initrd_populate_root_fs(initrd_paddr, initrd_size); +} + +struct inode* vfs_get_root(void) { + ASSERT(root); + inode_ref(root); + return root; +} + typedef struct mount_point { struct inode* host; struct inode* guest; struct mount_point* next; } mount_point; -typedef struct device { - struct inode* inode; - struct device* next; -} device; - -static struct inode* root; static mount_point* mount_points; static mutex mount_lock; -static device* devices; static int mount_at(struct inode* host, struct inode* guest) { if (!S_ISDIR(host->mode)) { @@ -79,11 +91,12 @@ int vfs_mount(const char* path, struct inode* fs_root) { return mount_at(inode, fs_root); } -struct inode* vfs_get_root(void) { - ASSERT(root); - inode_ref(root); - return root; -} +typedef struct device { + struct inode* inode; + struct device* next; +} device; + +static device* devices; int vfs_register_device(struct inode* inode) { device** dest = &devices; @@ -109,7 +122,7 @@ int vfs_register_device(struct inode* inode) { return 0; } -static struct inode* find_device(dev_t id) { +struct inode* vfs_get_device(dev_t id) { device* it = devices; while (it) { if (it->inode->device_id == id) { @@ -386,7 +399,7 @@ file_description* vfs_open(const char* pathname, int flags, mode_t mode) { return ERR_CAST(inode); if (S_ISBLK(inode->mode) || S_ISCHR(inode->mode)) { - struct inode* device = find_device(inode->device_id); + struct inode* device = vfs_get_device(inode->device_id); inode_unref(inode); if (!device) return ERR_PTR(-ENODEV); @@ -402,7 +415,7 @@ int vfs_stat(const char* pathname, struct stat* buf) { return PTR_ERR(inode); if (S_ISBLK(inode->mode) || S_ISCHR(inode->mode)) { - struct inode* device = find_device(inode->device_id); + struct inode* device = vfs_get_device(inode->device_id); inode_unref(inode); if (!device) return -ENODEV; diff --git a/kernel/graphics/graphics.h b/kernel/graphics/graphics.h deleted file mode 100644 index 80df0c4b..00000000 --- a/kernel/graphics/graphics.h +++ /dev/null @@ -1,15 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include - -NODISCARD bool fb_init(const multiboot_info_t* mb_info); -NODISCARD int fb_get_info(struct fb_info*); -NODISCARD int fb_set_info(struct fb_info*); -NODISCARD int fb_mmap(uintptr_t addr, size_t length, off_t offset, - uint16_t page_flags); - -struct inode* fb_device_get(void); diff --git a/kernel/kprintf.c b/kernel/kprintf.c index 8103b179..cb5afd32 100644 --- a/kernel/kprintf.c +++ b/kernel/kprintf.c @@ -1,5 +1,5 @@ #include "kprintf.h" -#include "serial.h" +#include "drivers/serial/serial.h" #include #include #include diff --git a/kernel/main.c b/kernel/main.c index 6b5c7569..5efe08e4 100644 --- a/kernel/main.c +++ b/kernel/main.c @@ -1,8 +1,8 @@ #include "api/sys/stat.h" #include "boot_defs.h" #include "console/console.h" -#include "graphics/graphics.h" -#include "hid/hid.h" +#include "drivers/drivers.h" +#include "drivers/serial/serial.h" #include "interrupts.h" #include "kprintf.h" #include "memory.h" @@ -11,11 +11,10 @@ #include "panic.h" #include "process.h" #include "scheduler.h" -#include "serial.h" #include "syscall/syscall.h" #include "time.h" -static noreturn void init(void) { +static noreturn void userland_init(void) { current->pid = current->pgid = process_generate_next_pid(); const char* init_path = cmdline_lookup("init"); @@ -31,20 +30,11 @@ static noreturn void init(void) { extern unsigned char kernel_end[]; extern unsigned char stack_top[]; -static void create_char_device(const char* pathname, struct inode* device) { - ASSERT_OK(vfs_register_device(device)); - - struct inode* inode = vfs_create(pathname, S_IFCHR); - ASSERT_OK(inode); - inode->device_id = device->device_id; - inode_unref(inode); -} - void start(uint32_t mb_magic, uintptr_t mb_info_paddr) { gdt_init(); idt_init(); irq_init(); - serial_init(); + serial_early_init(); kputs("\x1b[32mBooted\x1b[m\n"); sti(); @@ -54,70 +44,28 @@ void start(uint32_t mb_magic, uintptr_t mb_info_paddr) { const multiboot_info_t* mb_info = (const multiboot_info_t*)(mb_info_paddr + KERNEL_VADDR); - - cmdline_init(mb_info); - if (!(mb_info->flags & MULTIBOOT_INFO_MODS) || mb_info->mods_count == 0) PANIC("No initrd found. Provide initrd as the first Multiboot module"); - const multiboot_module_t* initrd_mod = - (const multiboot_module_t*)(mb_info->mods_addr + KERNEL_VADDR); - uintptr_t initrd_paddr = initrd_mod->mod_start; - uintptr_t initrd_size = initrd_mod->mod_end - initrd_mod->mod_start; + multiboot_module_t initrd_mod; + memcpy(&initrd_mod, + (const multiboot_module_t*)(mb_info->mods_addr + KERNEL_VADDR), + sizeof(multiboot_module_t)); + cmdline_init(mb_info); paging_init(mb_info); - - ASSERT_OK(vfs_mount(ROOT_DIR, tmpfs_create_root())); - + vfs_init(); process_init(); + drivers_init(mb_info); + vfs_populate_root_fs(&initrd_mod); random_init(); - - initrd_populate_root_fs(initrd_paddr, initrd_size); - - ASSERT_OK(vfs_mount("/dev", tmpfs_create_root())); - ASSERT_OK(vfs_register_device(null_device_get())); - ASSERT_OK(vfs_register_device(zero_device_get())); - ASSERT_OK(vfs_register_device(full_device_get())); - ASSERT_OK(vfs_register_device(random_device_get())); - ASSERT_OK(vfs_register_device(urandom_device_get())); - - if (ps2_init()) { - create_char_device("/dev/kbd", ps2_keyboard_device_get()); - create_char_device("/dev/psaux", ps2_mouse_device_get()); - } - - if (fb_init(mb_info)) { - create_char_device("/dev/fb0", fb_device_get()); - fb_console_init(); - create_char_device("/dev/tty", fb_console_device_get()); - } - - if (ac97_init()) - create_char_device("/dev/dsp", ac97_device_get()); - - serial_console_init(); - if (serial_enable_port(SERIAL_COM1)) - create_char_device("/dev/ttyS0", - serial_console_device_create(SERIAL_COM1)); - if (serial_enable_port(SERIAL_COM2)) - create_char_device("/dev/ttyS1", - serial_console_device_create(SERIAL_COM2)); - if (serial_enable_port(SERIAL_COM2)) - create_char_device("/dev/ttyS2", - serial_console_device_create(SERIAL_COM3)); - if (serial_enable_port(SERIAL_COM3)) - create_char_device("/dev/ttyS3", - serial_console_device_create(SERIAL_COM4)); - - system_console_init(); - ASSERT_OK(vfs_register_device(system_console_device_get())); - + console_init(); syscall_init(); scheduler_init(); time_init(); pit_init(); kputs("\x1b[32mInitialization done\x1b[m\n"); - ASSERT_OK(process_spawn_kernel_process("userland_init", init)); + ASSERT_OK(process_spawn_kernel_process("userland_init", userland_init)); process_exit(0); } diff --git a/kernel/system.c b/kernel/system.c index bca2aa2d..a40adfae 100644 --- a/kernel/system.c +++ b/kernel/system.c @@ -1,7 +1,7 @@ #include "system.h" #include "asm_wrapper.h" #include "boot_defs.h" -#include "hid/hid.h" +#include "drivers/hid/hid.h" #include "kprintf.h" #include "panic.h" #include "safe_string.h" diff --git a/kernel/system.h b/kernel/system.h index ecacd488..5dc337b5 100644 --- a/kernel/system.h +++ b/kernel/system.h @@ -2,7 +2,6 @@ #include "api/sys/types.h" #include "forward.h" -#include #include #include #include @@ -43,12 +42,3 @@ ssize_t random_get(void* buffer, size_t count); noreturn void reboot(void); noreturn void halt(void); noreturn void poweroff(void); - -struct inode* null_device_get(void); -struct inode* zero_device_get(void); -struct inode* full_device_get(void); -struct inode* random_device_get(void); -struct inode* urandom_device_get(void); - -NODISCARD bool ac97_init(void); -struct inode* ac97_device_get(void); diff --git a/userland/init.c b/userland/init.c index 48ee88f7..2ad760bf 100644 --- a/userland/init.c +++ b/userland/init.c @@ -1,3 +1,4 @@ +#include #include #include #include @@ -28,6 +29,29 @@ static pid_t spawn(char* filename) { return pid; } +struct device_file { + const char* pathname; + mode_t mode; + dev_t dev; +}; + +static void try_mknod(const struct device_file* file) { + if (mknod(file->pathname, file->mode, file->dev) < 0) { + perror("mknod"); + return; + } + + int rc = open(file->pathname, 0); + if (rc >= 0) + return; + if (errno != ENODEV) { + perror("open"); + return; + } + if (unlink(file->pathname) < 0) + perror("unlink"); +} + int main(void) { ASSERT(getpid() == 1); @@ -36,18 +60,26 @@ int main(void) { ASSERT(open("/dev/console", O_WRONLY) == STDOUT_FILENO); ASSERT(open("/dev/console", O_WRONLY) == STDERR_FILENO); - struct { - const char* pathname; - dev_t dev; - } dev_files[] = { - {"/dev/null", makedev(1, 3)}, {"/dev/zero", makedev(1, 5)}, - {"/dev/full", makedev(1, 7)}, {"/dev/random", makedev(1, 8)}, - {"/dev/urandom", makedev(1, 9)}, + ASSERT_OK(mount("tmpfs", "/dev", "tmpfs", 0, NULL)); + + const struct device_file device_files[] = { + {"/dev/null", S_IFCHR, makedev(1, 3)}, + {"/dev/zero", S_IFCHR, makedev(1, 5)}, + {"/dev/full", S_IFCHR, makedev(1, 7)}, + {"/dev/random", S_IFCHR, makedev(1, 8)}, + {"/dev/urandom", S_IFCHR, makedev(1, 9)}, + {"/dev/ttyS0", S_IFCHR, makedev(4, 64)}, + {"/dev/ttyS1", S_IFCHR, makedev(4, 65)}, + {"/dev/ttyS2", S_IFCHR, makedev(4, 66)}, + {"/dev/ttyS3", S_IFCHR, makedev(4, 67)}, + {"/dev/tty", S_IFCHR, makedev(5, 0)}, + {"/dev/psaux", S_IFCHR, makedev(10, 1)}, + {"/dev/kbd", S_IFCHR, makedev(11, 0)}, + {"/dev/dsp", S_IFCHR, makedev(14, 3)}, + {"/dev/fb0", S_IFBLK, makedev(29, 0)}, }; - for (size_t i = 0; i < ARRAY_SIZE(dev_files); ++i) { - if (mknod(dev_files[i].pathname, S_IFCHR, dev_files[i].dev) < 0) - perror("mknod"); - } + for (size_t i = 0; i < ARRAY_SIZE(device_files); ++i) + try_mknod(&device_files[i]); if (mount("tmpfs", "/tmp", "tmpfs", 0, NULL) < 0) perror("mount");