From: Simon Kuenzer Date: Thu, 19 Sep 2024 15:20:58 +0000 (+0200) Subject: drivers/vgacons: Rename `libukconsole_vga` to `libvgacons` X-Git-Tag: RELEASE-0.18.0~14 X-Git-Url: http://xenbits.xensource.com/gitweb?a=commitdiff_plain;h=bd4d16a27b4e36cbb85800bcf2f201ae6d3a574e;p=unikraft%2Funikraft.git drivers/vgacons: Rename `libukconsole_vga` to `libvgacons` Rename the driver library and driver directory to `libvgacons` to provide a naming scheme that is more appropriate for general purpose devices and to highlight that this driver is inteded for text-mode only. Configuration options are adopted accordingly. Signed-off-by: Simon Kuenzer Reviewed-by: Oleksii Moisieiev Reviewed-by: Oleksii Moisieiev Reviewed-by: Michalis Pappas Approved-by: Michalis Pappas GitHub-Closes: #1501 --- diff --git a/drivers/ukconsole/Makefile.uk b/drivers/ukconsole/Makefile.uk index af2b064eb..b87d42be0 100644 --- a/drivers/ukconsole/Makefile.uk +++ b/drivers/ukconsole/Makefile.uk @@ -8,4 +8,4 @@ UK_DRIV_CONSOLE_BASE := $(UK_DRIV_BASE)/ukconsole $(eval $(call import_lib,$(UK_DRIV_CONSOLE_BASE)/ns16550)) $(eval $(call import_lib,$(UK_DRIV_CONSOLE_BASE)/pl011)) -$(eval $(call import_lib,$(UK_DRIV_CONSOLE_BASE)/vga)) +$(eval $(call import_lib,$(UK_DRIV_CONSOLE_BASE)/vgacons)) diff --git a/drivers/ukconsole/vga/Config.uk b/drivers/ukconsole/vga/Config.uk deleted file mode 100644 index 41906d2f7..000000000 --- a/drivers/ukconsole/vga/Config.uk +++ /dev/null @@ -1,5 +0,0 @@ -config LIBUKCONSOLE_VGA - bool "VGA console driver" - depends on ARCH_X86_64 - depends on LIBUKCONSOLE - select LIBNOLIBC if !HAVE_LIBC diff --git a/drivers/ukconsole/vga/Makefile.uk b/drivers/ukconsole/vga/Makefile.uk deleted file mode 100644 index 5df981fc1..000000000 --- a/drivers/ukconsole/vga/Makefile.uk +++ /dev/null @@ -1,6 +0,0 @@ -$(eval $(call addlib_s,libukconsole_vga,$(CONFIG_LIBUKCONSOLE_VGA))) - -# TODO: Remove as soon as plat dependencies go away -LIBUKCONSOLE_VGA_CINCLUDES-y += -I$(UK_PLAT_COMMON_BASE)/include - -LIBUKCONSOLE_VGA_SRCS-y += $(LIBUKCONSOLE_VGA_BASE)/vga.c diff --git a/drivers/ukconsole/vga/exportsyms.uk b/drivers/ukconsole/vga/exportsyms.uk deleted file mode 100644 index 8b1378917..000000000 --- a/drivers/ukconsole/vga/exportsyms.uk +++ /dev/null @@ -1 +0,0 @@ - diff --git a/drivers/ukconsole/vga/vga.c b/drivers/ukconsole/vga/vga.c deleted file mode 100644 index 77f440805..000000000 --- a/drivers/ukconsole/vga/vga.c +++ /dev/null @@ -1,271 +0,0 @@ -/* SPDX-License-Identifier: ISC */ -/* - * Authors: Dan Williams - * Martin Lucina - * Felipe Huici - * Florian Schmidt - * Simon Kuenzer - * Dafna Hirschfeld - * - * Copyright (c) 2015-2017 IBM - * Copyright (c) 2016-2017 Docker, Inc. - * Copyright (c) 2017 NEC Europe Ltd., NEC Corporation - * - * Permission to use, copy, modify, and/or distribute this software - * for any purpose with or without fee is hereby granted, provided - * that the above copyright notice and this permission notice appear - * in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL - * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE - * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR - * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS - * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, - * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN - * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -/* Hardware text mode color constants. */ -enum vga_color { - VGA_COLOR_BLACK = 0, - VGA_COLOR_BLUE = 1, - VGA_COLOR_GREEN = 2, - VGA_COLOR_CYAN = 3, - VGA_COLOR_RED = 4, - VGA_COLOR_MAGENTA = 5, - VGA_COLOR_BROWN = 6, - VGA_COLOR_LIGHT_GREY = 7, - VGA_COLOR_DARK_GREY = 8, - VGA_COLOR_LIGHT_BLUE = 9, - VGA_COLOR_LIGHT_GREEN = 10, - VGA_COLOR_LIGHT_CYAN = 11, - VGA_COLOR_LIGHT_RED = 12, - VGA_COLOR_LIGHT_MAGENTA = 13, - VGA_COLOR_LIGHT_BROWN = 14, - VGA_COLOR_WHITE = 15, -}; - -static inline uint8_t vga_entry_color(enum vga_color fg, enum vga_color bg) -{ - return fg | bg << 4; -} - -static inline uint16_t vga_entry(unsigned char uc, uint8_t color) -{ - return (uint16_t) uc | (uint16_t) color << 8; -} - -#define TAB_ALIGNMENT 8 -#define VGA_WIDTH 80 -#define VGA_HEIGHT 25 -#define VGA_FB_BASE 0xb8000 -#define X86_VIDEO_MEM_START 0xA0000UL -#define X86_VIDEO_MEM_LEN 0x20000UL - - -static size_t terminal_row; -static size_t terminal_column; -static uint8_t terminal_color; -static uint16_t *const terminal_buffer = (uint16_t *)VGA_FB_BASE; -static uint16_t areg; /* VGA address register */ -static uint16_t dreg; /* VGA data register */ - -static void clear_terminal(void) -{ - for (size_t y = 0; y < VGA_HEIGHT; y++) { - for (size_t x = 0; x < VGA_WIDTH; x++) { - const size_t index = y * VGA_WIDTH + x; - - terminal_buffer[index] = vga_entry(' ', terminal_color); - } - } -} - -static void terminal_putentryat(char c, uint8_t color, size_t x, size_t y) -{ - const size_t index = y * VGA_WIDTH + x; - - terminal_buffer[index] = vga_entry(c, color); -} -static void vga_scroll(void) -{ - size_t i; - - for (i = 1; i < VGA_HEIGHT; i++) { - memcpy(terminal_buffer + ((i - 1) * VGA_WIDTH), - terminal_buffer + (i * VGA_WIDTH), VGA_WIDTH * 2); - } - for (i = 0; i < VGA_WIDTH; i++) - terminal_buffer[((VGA_HEIGHT - 1) * VGA_WIDTH) + i] - = vga_entry(' ', terminal_color); -} - -static void vga_update_cursor(void) -{ - unsigned long irq_flags; - uint8_t old; - - local_irq_save(irq_flags); - old = inb(areg); - outb(areg, 0x0e); // Cursor Location High - outb(dreg, ((terminal_row * VGA_WIDTH) + terminal_column) >> 8); - outb(areg, 0x0f); // Cursor Location Low - outb(dreg, ((terminal_row * VGA_WIDTH) + terminal_column) & 0xff); - outb(areg, old); - local_irq_restore(irq_flags); -} - -static void vga_putc(char c) -{ -#define NEWLINE() \ - do { \ - if (row == VGA_HEIGHT - 1) \ - vga_scroll(); \ - else \ - row++; \ - } while (0) - - unsigned long irq_flags; - size_t row; - size_t column; - - /* Make a consistent copy of the global state variables (row, column). - * This way, we can work on them consistently in this function and - * and prevent race conditions on them that could lead to writing - * outside the video memory. This doesn't make the function behave - * perfectly on reentrance (lines can still be overwritten by - * code paths running through this function concurrently), but at - * least we stay inside the video memory. - */ - local_irq_save(irq_flags); - row = terminal_row; - column = terminal_column; - local_irq_restore(irq_flags); - - switch (c) { - case '\a': - break; //ascii bel (0x07) - ignore - case '\b': - if (column > 0) { - column--; - } else if (row > 0) { - column = VGA_WIDTH - 1; - row--; - } - break; - case '\n': - NEWLINE(); - __fallthrough; - case '\r': - column = 0; - break; - case '\t': - do { - column++; - } while (column % TAB_ALIGNMENT != 0 - && column != VGA_WIDTH); - - if (column == VGA_WIDTH) { - column = 0; - NEWLINE(); - } - break; - default: - terminal_putentryat(c, terminal_color, - column, row); - if (++column == VGA_WIDTH) { - column = 0; - NEWLINE(); - } - break; - } - - local_irq_save(irq_flags); - terminal_row = row; - terminal_column = column; - local_irq_restore(irq_flags); - - vga_update_cursor(); -} - -static __ssz vga_console_out(struct uk_console *dev __unused, - const char *buf, __sz len) -{ - for (__sz i = 0; i < len; i++) - vga_putc(buf[i]); - return len; -} - -static struct uk_console_ops vga_ops = { .out = vga_console_out }; - -static struct uk_console vga_dev; - -static int vga_init(struct ukplat_bootinfo *bi) -{ - unsigned long irq_flags; - struct ukplat_memregion_desc mrd = {0}; - int rc; - - terminal_row = 0; - terminal_column = 0; - terminal_color = vga_entry_color(VGA_COLOR_LIGHT_GREY, VGA_COLOR_BLACK); - - local_irq_save(irq_flags); - /* Location of the address and data registers is variable and denoted - * by the least significant bit in the Input/Output register located - * at 0x3cc. For our emulated color display, they should always be - * 0x3d{4,5}, but better safe than sorry, so let's check at init time. - */ - if (inb(0x3cc) & 0x1) { - areg = 0x3d4; - dreg = 0x3d5; - } else { - areg = 0x3b4; - dreg = 0x3b5; - } - - /* Initialize cursor appearance. Setting CURSOR_START (0x0a) to 0x0e - * and CURSOR_END (0x0b) to 0x0f enables the cursor and produces - * a blinking underscore. - */ - outb(areg, 0x0a); - outb(dreg, 0x0e); - outb(areg, 0x0b); - outb(dreg, 0x0f); - local_irq_restore(irq_flags); - - clear_terminal(); - - uk_console_init(&vga_dev, "VGA", &vga_ops, UK_CONSOLE_FLAG_STDOUT); - uk_console_register(&vga_dev); - - mrd.pbase = X86_VIDEO_MEM_START; - mrd.vbase = X86_VIDEO_MEM_START; - mrd.pg_off = 0; - mrd.len = X86_VIDEO_MEM_LEN; - mrd.pg_count = PAGE_COUNT(X86_VIDEO_MEM_LEN); - mrd.type = UKPLAT_MEMRT_RESERVED; - mrd.flags = UKPLAT_MEMRF_READ | UKPLAT_MEMRF_WRITE; - rc = ukplat_memregion_list_insert(&bi->mrds, &mrd); - if (unlikely(rc < 0)) { - uk_pr_err("Could not insert mrd (%d)\n", rc); - return rc; - } - - return 0; -} - -UK_BOOT_EARLYTAB_ENTRY(vga_init, UK_PRIO_AFTER(UK_PRIO_EARLIEST)); diff --git a/drivers/ukconsole/vgacons/Config.uk b/drivers/ukconsole/vgacons/Config.uk new file mode 100644 index 000000000..df6c3b4a5 --- /dev/null +++ b/drivers/ukconsole/vgacons/Config.uk @@ -0,0 +1,5 @@ +config LIBVGACONS + bool "VGA console driver" + depends on ARCH_X86_64 + depends on LIBUKCONSOLE + select LIBNOLIBC if !HAVE_LIBC diff --git a/drivers/ukconsole/vgacons/Makefile.uk b/drivers/ukconsole/vgacons/Makefile.uk new file mode 100644 index 000000000..fd43d9447 --- /dev/null +++ b/drivers/ukconsole/vgacons/Makefile.uk @@ -0,0 +1,6 @@ +$(eval $(call addlib_s,libvgacons,$(CONFIG_LIBVGACONS))) + +# TODO: Remove as soon as plat dependencies go away +LIBVGACONS_CINCLUDES-y += -I$(UK_PLAT_COMMON_BASE)/include + +LIBVGACONS_SRCS-y += $(LIBVGACONS_BASE)/vga.c diff --git a/drivers/ukconsole/vgacons/exportsyms.uk b/drivers/ukconsole/vgacons/exportsyms.uk new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/drivers/ukconsole/vgacons/exportsyms.uk @@ -0,0 +1 @@ + diff --git a/drivers/ukconsole/vgacons/vga.c b/drivers/ukconsole/vgacons/vga.c new file mode 100644 index 000000000..1ba8c3ded --- /dev/null +++ b/drivers/ukconsole/vgacons/vga.c @@ -0,0 +1,271 @@ +/* SPDX-License-Identifier: ISC */ +/* + * Authors: Dan Williams + * Martin Lucina + * Felipe Huici + * Florian Schmidt + * Simon Kuenzer + * Dafna Hirschfeld + * + * Copyright (c) 2015-2017 IBM + * Copyright (c) 2016-2017 Docker, Inc. + * Copyright (c) 2017 NEC Europe Ltd., NEC Corporation + * + * Permission to use, copy, modify, and/or distribute this software + * for any purpose with or without fee is hereby granted, provided + * that the above copyright notice and this permission notice appear + * in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +/* Hardware text mode color constants. */ +enum vga_color { + VGA_COLOR_BLACK = 0, + VGA_COLOR_BLUE = 1, + VGA_COLOR_GREEN = 2, + VGA_COLOR_CYAN = 3, + VGA_COLOR_RED = 4, + VGA_COLOR_MAGENTA = 5, + VGA_COLOR_BROWN = 6, + VGA_COLOR_LIGHT_GREY = 7, + VGA_COLOR_DARK_GREY = 8, + VGA_COLOR_LIGHT_BLUE = 9, + VGA_COLOR_LIGHT_GREEN = 10, + VGA_COLOR_LIGHT_CYAN = 11, + VGA_COLOR_LIGHT_RED = 12, + VGA_COLOR_LIGHT_MAGENTA = 13, + VGA_COLOR_LIGHT_BROWN = 14, + VGA_COLOR_WHITE = 15, +}; + +static inline uint8_t vga_entry_color(enum vga_color fg, enum vga_color bg) +{ + return fg | bg << 4; +} + +static inline uint16_t vga_entry(unsigned char uc, uint8_t color) +{ + return (uint16_t) uc | (uint16_t) color << 8; +} + +#define TAB_ALIGNMENT 8 +#define VGA_WIDTH 80 +#define VGA_HEIGHT 25 +#define VGA_FB_BASE 0xb8000 +#define X86_VIDEO_MEM_START 0xA0000UL +#define X86_VIDEO_MEM_LEN 0x20000UL + + +static size_t terminal_row; +static size_t terminal_column; +static uint8_t terminal_color; +static uint16_t *const terminal_buffer = (uint16_t *)VGA_FB_BASE; +static uint16_t areg; /* VGA address register */ +static uint16_t dreg; /* VGA data register */ + +static void clear_terminal(void) +{ + for (size_t y = 0; y < VGA_HEIGHT; y++) { + for (size_t x = 0; x < VGA_WIDTH; x++) { + const size_t index = y * VGA_WIDTH + x; + + terminal_buffer[index] = vga_entry(' ', terminal_color); + } + } +} + +static void terminal_putentryat(char c, uint8_t color, size_t x, size_t y) +{ + const size_t index = y * VGA_WIDTH + x; + + terminal_buffer[index] = vga_entry(c, color); +} +static void vga_scroll(void) +{ + size_t i; + + for (i = 1; i < VGA_HEIGHT; i++) { + memcpy(terminal_buffer + ((i - 1) * VGA_WIDTH), + terminal_buffer + (i * VGA_WIDTH), VGA_WIDTH * 2); + } + for (i = 0; i < VGA_WIDTH; i++) + terminal_buffer[((VGA_HEIGHT - 1) * VGA_WIDTH) + i] + = vga_entry(' ', terminal_color); +} + +static void vga_update_cursor(void) +{ + unsigned long irq_flags; + uint8_t old; + + local_irq_save(irq_flags); + old = inb(areg); + outb(areg, 0x0e); // Cursor Location High + outb(dreg, ((terminal_row * VGA_WIDTH) + terminal_column) >> 8); + outb(areg, 0x0f); // Cursor Location Low + outb(dreg, ((terminal_row * VGA_WIDTH) + terminal_column) & 0xff); + outb(areg, old); + local_irq_restore(irq_flags); +} + +static void vga_putc(char c) +{ +#define NEWLINE() \ + do { \ + if (row == VGA_HEIGHT - 1) \ + vga_scroll(); \ + else \ + row++; \ + } while (0) + + unsigned long irq_flags; + size_t row; + size_t column; + + /* Make a consistent copy of the global state variables (row, column). + * This way, we can work on them consistently in this function and + * and prevent race conditions on them that could lead to writing + * outside the video memory. This doesn't make the function behave + * perfectly on reentrance (lines can still be overwritten by + * code paths running through this function concurrently), but at + * least we stay inside the video memory. + */ + local_irq_save(irq_flags); + row = terminal_row; + column = terminal_column; + local_irq_restore(irq_flags); + + switch (c) { + case '\a': + break; //ascii bel (0x07) - ignore + case '\b': + if (column > 0) { + column--; + } else if (row > 0) { + column = VGA_WIDTH - 1; + row--; + } + break; + case '\n': + NEWLINE(); + __fallthrough; + case '\r': + column = 0; + break; + case '\t': + do { + column++; + } while (column % TAB_ALIGNMENT != 0 + && column != VGA_WIDTH); + + if (column == VGA_WIDTH) { + column = 0; + NEWLINE(); + } + break; + default: + terminal_putentryat(c, terminal_color, + column, row); + if (++column == VGA_WIDTH) { + column = 0; + NEWLINE(); + } + break; + } + + local_irq_save(irq_flags); + terminal_row = row; + terminal_column = column; + local_irq_restore(irq_flags); + + vga_update_cursor(); +} + +static __ssz vga_console_out(struct uk_console *dev __unused, + const char *buf, __sz len) +{ + for (__sz i = 0; i < len; i++) + vga_putc(buf[i]); + return len; +} + +static struct uk_console_ops vga_ops = { .out = vga_console_out }; + +static struct uk_console vga_dev; + +static int vga_init(struct ukplat_bootinfo *bi) +{ + unsigned long irq_flags; + struct ukplat_memregion_desc mrd = {0}; + int rc; + + terminal_row = 0; + terminal_column = 0; + terminal_color = vga_entry_color(VGA_COLOR_LIGHT_GREY, VGA_COLOR_BLACK); + + local_irq_save(irq_flags); + /* Location of the address and data registers is variable and denoted + * by the least significant bit in the Input/Output register located + * at 0x3cc. For our emulated color display, they should always be + * 0x3d{4,5}, but better safe than sorry, so let's check at init time. + */ + if (inb(0x3cc) & 0x1) { + areg = 0x3d4; + dreg = 0x3d5; + } else { + areg = 0x3b4; + dreg = 0x3b5; + } + + /* Initialize cursor appearance. Setting CURSOR_START (0x0a) to 0x0e + * and CURSOR_END (0x0b) to 0x0f enables the cursor and produces + * a blinking underscore. + */ + outb(areg, 0x0a); + outb(dreg, 0x0e); + outb(areg, 0x0b); + outb(dreg, 0x0f); + local_irq_restore(irq_flags); + + clear_terminal(); + + uk_console_init(&vga_dev, "vgacons", &vga_ops, UK_CONSOLE_FLAG_STDOUT); + uk_console_register(&vga_dev); + + mrd.pbase = X86_VIDEO_MEM_START; + mrd.vbase = X86_VIDEO_MEM_START; + mrd.pg_off = 0; + mrd.len = X86_VIDEO_MEM_LEN; + mrd.pg_count = PAGE_COUNT(X86_VIDEO_MEM_LEN); + mrd.type = UKPLAT_MEMRT_RESERVED; + mrd.flags = UKPLAT_MEMRF_READ | UKPLAT_MEMRF_WRITE; + rc = ukplat_memregion_list_insert(&bi->mrds, &mrd); + if (unlikely(rc < 0)) { + uk_pr_err("Could not insert mrd (%d)\n", rc); + return rc; + } + + return 0; +} + +UK_BOOT_EARLYTAB_ENTRY(vga_init, UK_PRIO_AFTER(UK_PRIO_EARLIEST)); diff --git a/plat/kvm/Config.uk b/plat/kvm/Config.uk index 7f01d549e..bec0ef02f 100644 --- a/plat/kvm/Config.uk +++ b/plat/kvm/Config.uk @@ -102,7 +102,7 @@ config KVM_VMM_QEMU imply LIBNS16550_COM1 if LIBUKCONSOLE && ARCH_X86_64 imply LIBUKINTCTLR_GICV2 if ARCH_ARM_64 imply LIBUKRTC_PL031 - imply LIBUKCONSOLE_VGA if ARCH_X86_64 + imply LIBVGACONS if ARCH_X86_64 select HAVE_PCI select HAVE_MMIO