#include #include #include #include #include #include struct vga_console { uint16_t *vga_framebuffer; unsigned int vga_cursor_x, vga_cursor_y; unsigned int vga_screen_width, vga_screen_height; uint8_t vga_attrib; }; static struct vga_console vga_con = { .vga_attrib = 0x0F, .vga_screen_width = 80, .vga_screen_height = 25, .vga_framebuffer = (uint16_t *)0xffffffff800b8000, }; static void vga_console_clear(struct vga_console *con) { size_t len = con->vga_screen_width * con->vga_screen_height; for (size_t i = 0; i < len; i++) { con->vga_framebuffer[i] = (uint16_t)con->vga_attrib << 8; } con->vga_cursor_x = 0; con->vga_cursor_y = 0; } static void vga_console_show_cursor(struct vga_console *con) { size_t start = 0, end = 15; outportb(0x3D4, 0x0A); outportb(0x3D5, (inportb(0x3D5) & 0xC0) | start); outportb(0x3D4, 0x0B); outportb(0x3D5, (inportb(0x3D5) & 0xE0) | end); } static void vga_console_update_cursor(struct vga_console *con) { uint16_t pos = con->vga_cursor_y * con->vga_screen_width + con->vga_cursor_x; outportb(0x3D4, 0x0F); outportb(0x3D5, (uint8_t)(pos & 0xFF)); outportb(0x3D4, 0x0E); outportb(0x3D5, (uint8_t)((pos >> 8) & 0xFF)); } static void vga_console_scroll(struct vga_console *con) { uint16_t *src = &con->vga_framebuffer[con->vga_screen_width]; uint16_t *dest = &con->vga_framebuffer[0]; size_t len = (con->vga_screen_height - 1) * con->vga_screen_width * sizeof *con->vga_framebuffer; memcpy(dest, src, len); dest = &con->vga_framebuffer [(con->vga_screen_height - 1) * con->vga_screen_width]; len = con->vga_screen_width; for (size_t i = 0; i < len; i++) { dest[i] = (uint16_t)con->vga_attrib << 8; } con->vga_cursor_x = 0; con->vga_cursor_y = con->vga_screen_height - 1; } static void vga_console_putc(struct vga_console *con, char c) { switch (c) { case '\n': con->vga_cursor_x = 0; con->vga_cursor_y++; break; case '\r': con->vga_cursor_x = 0; break; default: con->vga_framebuffer [con->vga_cursor_y * con->vga_screen_width + con->vga_cursor_x] = ((uint16_t)con->vga_attrib << 8) | c; con->vga_cursor_x++; break; } if (con->vga_cursor_x >= con->vga_screen_width) { con->vga_cursor_x = 0; con->vga_cursor_y++; } if (con->vga_cursor_y >= con->vga_screen_height) { vga_console_scroll(con); } } static void vgacon_write(struct console *con, const char *s, unsigned int len) { for (unsigned int i = 0; i < len; i++) { vga_console_putc(&vga_con, s[i]); } vga_console_update_cursor(&vga_con); } static struct console vgacon = { .c_name = "vgacon", .c_flags = CON_BOOT, .c_write = vgacon_write, .c_lock = SPIN_LOCK_INIT, }; void vgacon_init(void) { vga_console_clear(&vga_con); vga_console_show_cursor(&vga_con); console_register(&vgacon); }