From d963772c6633a0610898aaba2ae90d461e8f2de8 Mon Sep 17 00:00:00 2001 From: nishi Date: Fri, 7 Jul 2023 23:40:27 +0000 Subject: should be working, should be git-svn-id: https://svn.vegaa.systems/svn/vega-Vega/trunk@7 a8a8aea2-181d-ee11-89e8-15fd0e089fc4 --- sys/kern/init_main.c | 59 ++++++++ sys/kern/kern_panic.c | 58 ++++++++ sys/kern/kern_syslog.c | 96 ++++++++++++ sys/kern/tty.c | 387 +++++++++++++++++++++++++++++++++++++++++++++++++ sys/kern/tty_subr.c | 59 ++++++++ 5 files changed, 659 insertions(+) create mode 100644 sys/kern/init_main.c create mode 100644 sys/kern/kern_panic.c create mode 100644 sys/kern/kern_syslog.c create mode 100644 sys/kern/tty.c create mode 100644 sys/kern/tty_subr.c (limited to 'sys/kern') diff --git a/sys/kern/init_main.c b/sys/kern/init_main.c new file mode 100644 index 0000000..2ae2a09 --- /dev/null +++ b/sys/kern/init_main.c @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2023 Ian Marco Moffett and the VegaOS team. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of VegaOS nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* $Id$ */ + +#include +#include +#include +#include +#include +#include + +__KERNEL_META("$Vega$: init_main.c, Ian Marco Moffett, " + "Where the Vega kernel first starts up"); + +static struct processor bsp = { + .gdtr = &g_early_gdtr, + .gdt = &g_dmmy_gdt[0] +}; + +void +main(void) +{ + tty_init(); + syslog_init(); + PRINT_LOGO(); + + processor_init(&bsp); + vm_physseg_init(); + + /* We're done here, halt the processor */ + __ASMV("cli; hlt"); +} diff --git a/sys/kern/kern_panic.c b/sys/kern/kern_panic.c new file mode 100644 index 0000000..69680f7 --- /dev/null +++ b/sys/kern/kern_panic.c @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2023 Ian Marco Moffett and the VegaOS team. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of VegaOS nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* $Id$ */ + +#include +#include +#include + +/* + * Tells the user something terribly + * wrong happened then halting the system + * as soon as possible. + * + * XXX: There is no need to cleanup stuff here (e.g `va_list ap`) + * as we won't be returning from here anyways and the source + * of the panic could be *anywhere* so it's best not to mess with + * things. + */ +void +panic(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + + kprintf("panic: "); + vkprintf(fmt, &ap); + + processor_halt(); + __builtin_unreachable(); +} diff --git a/sys/kern/kern_syslog.c b/sys/kern/kern_syslog.c new file mode 100644 index 0000000..cd7f8f0 --- /dev/null +++ b/sys/kern/kern_syslog.c @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2023 Ian Marco Moffett and the VegaOS team. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of VegaOS nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* $Id$ */ + +#include +#include +#include + +static struct tty syslog_tty; + +static void +syslog_handle_fmt(va_list *ap, char fmt_spec) +{ + char tmp_ch; + int64_t tmp_int; + const char *tmp_str; + char tmp_buf[256] = { 0 }; + + switch (fmt_spec) { + case 'c': + tmp_ch = va_arg(*ap, int); + tty_write(&syslog_tty, &tmp_ch, 1); + break; + case 's': + tmp_str = va_arg(*ap, const char *); + tty_write(&syslog_tty, tmp_str, strlen(tmp_str)); + break; + case 'd': + tmp_int = va_arg(*ap, int64_t); + itoa(tmp_int, tmp_buf, 10); + tty_write(&syslog_tty, tmp_buf, strlen(tmp_buf)); + break; + case 'x': + tmp_int = va_arg(*ap, uint64_t); + itoa(tmp_int, tmp_buf, 16); + tty_write(&syslog_tty, tmp_buf + 2, strlen(tmp_buf) - 2); + break; + } +} + +void +vkprintf(const char *fmt, va_list *ap) +{ + while (*fmt) { + if (*fmt == '%') { + ++fmt; + syslog_handle_fmt(ap, *fmt++); + } else { + tty_write(&syslog_tty, fmt++, 1); + } + } +} + +void +kprintf(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + vkprintf(fmt, &ap); + va_end(ap); +} + +void +syslog_init(void) +{ + tty_set_defaults(&syslog_tty); + tty_attach(&syslog_tty); +} diff --git a/sys/kern/tty.c b/sys/kern/tty.c new file mode 100644 index 0000000..f166302 --- /dev/null +++ b/sys/kern/tty.c @@ -0,0 +1,387 @@ +/* + * Copyright (c) 2023 Ian Marco Moffett and the VegaOS team. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of VegaOS nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* $Id$ */ + +#include +#include +#include +#include +#include +#include + +/* + * Default cursor color. + * + * TODO: The cursor color should + * be the invert of the color + * of whatever it is on top of. + */ +#define DEFAULT_CURSOR_BG 0x808080 + +#define CURSOR_WIDTH FONT_WIDTH +#define CURSOR_HEIGHT FONT_HEIGHT + +__KERNEL_META("$Vega$: tty.c, Ian Marco Moffett, " + "Core TTY implementation"); + +/* List of attached TTYs */ +static TAILQ_HEAD(, tty) tty_list; + +/* + * Renders a char onto the + * TTY specified by `tty`. + */ +static void +tty_draw_char(struct tty *tty, char c, uint32_t fg, uint32_t bg) +{ + uint32_t *fb_ptr; + uint32_t x, y; + size_t idx; + const uint8_t *glyph; + + /* Get a pointer to framebuffer memory */ + fb_ptr = tty->fbdev.mem; + + /* Get the specific glyph of `c` */ + glyph = &DEFAULT_FONT_DATA[(int)c*16]; + + x = tty->chpos_x; + y = tty->chpos_y; + + for (uint32_t cy = 0; cy < FONT_HEIGHT; ++cy) { + for (uint32_t cx = 0; cx < FONT_WIDTH; ++cx) { + idx = fbdev_get_index(&tty->fbdev, x+FONT_WIDTH-cx, y+cy); + fb_ptr[idx] = __TEST(glyph[cy], __BIT(cx)) ? fg : bg; + } + } +} + +/* + * Draws a cursor onto + * the screen. + * + * Call with TTY locked. + */ +static void +tty_draw_cursor(struct tty *tty, bool hide) +{ + uint32_t x, y, idx; + uint32_t *fb_ptr; + uint32_t color; + + fb_ptr = tty->fbdev.mem; + color = hide ? tty->bg : DEFAULT_CURSOR_BG; + + for (size_t cy = 0; cy < CURSOR_HEIGHT; ++cy) { + for (size_t cx = 0; cx < CURSOR_WIDTH; ++cx) { + x = tty->curspos_x + cx; + y = tty->curspos_y + cy; + idx = fbdev_get_index(&tty->fbdev, x, y); + fb_ptr[idx] = color; + } + } +} + +static void +tty_scroll_single(struct tty *tty) +{ + uint32_t *fb_ptr; + size_t line_size, dest_idx, src_idx; + + fb_ptr = tty->fbdev.mem; + line_size = tty->fbdev.pitch/4; + + /* Copy each line up */ + for (size_t y = FONT_HEIGHT; y < tty->t_ws_ypixel; y += FONT_HEIGHT) { + dest_idx = fbdev_get_index(&tty->fbdev, 0, y - FONT_HEIGHT); + src_idx = fbdev_get_index(&tty->fbdev, 0, y); + memcpy32(&fb_ptr[dest_idx], &fb_ptr[src_idx], FONT_HEIGHT*line_size); + } + + /* + * Ensure we start at X position 0 + * after we scrolled down. + */ + tty->chpos_x = 0; + tty->curspos_x = 0; +} + +/* + * Handles a newline. + * + * Call with TTY locked. + */ +static inline void +tty_newline(struct tty *tty) +{ + uint32_t ypos; + const uint32_t MAX_YPOS = tty->t_ws_ypixel - (CURSOR_HEIGHT*2); + + /* Hide the cursor */ + tty_draw_cursor(tty, true); + + /* Reset X positions */ + tty->chpos_x = 0; + tty->curspos_x = 0; + + /* + * Get the value closest to end + * of the screen. + */ + ypos = __MAX(tty->chpos_y, tty->curspos_y); + + /* + * Check if we need to scroll + * instead of incrementing + * Y positions. + */ + if (ypos < MAX_YPOS) { + tty->chpos_y += FONT_HEIGHT; + tty->curspos_y += FONT_HEIGHT; + } else { + tty_scroll_single(tty); + } + + /* Redraw the cursor */ + tty_draw_cursor(tty, false); +} + +/* + * Appends a character to the TTY specified + * by `tty` as well as incrementing tty->chpos_x + * and making newlines as needed. + * + * Call with TTY locked. + */ +static inline void +tty_append_char(struct tty *tty, int c) +{ + const uint32_t MAX_XPOS = tty->t_ws_xpixel - FONT_WIDTH; + + /* Hide the cursor */ + tty_draw_cursor(tty, true); + + tty_draw_char(tty, c, tty->fg, tty->bg); + tty->chpos_x += FONT_WIDTH; + tty->curspos_x += FONT_WIDTH; + + if (tty->chpos_x >= MAX_XPOS) { + tty_newline(tty); + } + + /* Redraw the cursor */ + tty_draw_cursor(tty, false); +} + +/* + * Writes out a tab as `tty->tab_width` + * spaces. + * + * Call with TTY locked. + */ +static void +tty_expand_tab(struct tty *tty) +{ + for (size_t i = 0; i < tty->tab_width; ++i) { + tty_append_char(tty, ' '); + } +} + +/* + * Writes a char to the TTY. + * + * Returns 0 on success; non-zero value + * is a character to be resent. + * + * Call with TTY locked. + */ +static int +tty_putch(struct tty *tty, int c) +{ + if (!__TEST(tty->t_oflag, OPOST)) { + /* + * Just write out the char with + * no processing. + */ + tty_append_char(tty, c); + return 0; + } + + switch (c) { + case ASCII_HT: + /* Tab */ + tty_expand_tab(tty); + break; + case ASCII_LF: + /* Line feed ('\n') */ + tty_newline(tty); + break; + default: + tty_append_char(tty, c); + break; + } + + return 0; +} + +/* + * Flushes a TTY specified + * by `tty`. + * + * Call with TTY locked. + */ +void +tty_flush(struct tty *tty) +{ + struct tty_ring *ring; + + ring = &tty->ring; + + /* + * Write each byte from the buffer + * to the screen with output processing + * if possible. + * + * XXX: Perhaps there could be a faster + * way of doing this instead of + * byte by byte? + */ + for (size_t i = 0; i < ring->len; ++i) { + tty_putch(tty, ring->buf[i]); + } + + ring->len = 0; +} + +/* + * Writes to a TTY specified by `tty`. + * + * @buf: Buffer to write. + * @len: Length of buffer. + * + * Returns number of bytes written, and + * EXIT_FAILURE on error. + */ +ssize_t +tty_write(struct tty *tty, const char *buf, size_t len) +{ + if (len == 0) { + /* Bad value, don't even try */ + return EXIT_FAILURE; + } + + TTY_LOCK(tty); + for (size_t i = 0; i < len; ++i) { + tty_push_char(tty, buf[i]); + /* + * If we have a newline and we are + * buffering bytes, flush the ring. + */ + if (buf[i] == '\n' && __TEST(tty->t_oflag, ORBUF)) { + tty_flush(tty); + } + } + + /* + * If we aren't buffering bytes, don't + * keep the bytes within the ring and + * flush it right away per `tty_write()` + * call. + */ + if (!__TEST(tty->t_oflag, ORBUF)) { + tty_flush(tty); + } + + TTY_UNLOCK(tty); + return len; +} + +/* + * Sets TTY fields to their defaults. + */ +void +tty_set_defaults(struct tty *tty) +{ + /* Ensure everything is initially zero */ + memset(tty, 0, sizeof(*tty)); + + /* + * Now, initialize everything to their defaults. + * + * Some notes about the default framebuffer device: + * ------------------------------------------------ + * The default framebuffer device should be the + * front buffer. Later on during boot, all attached + * TTYs shall have their fbdev swapped out with a + * backbuffer to improve performace as reading directly + * from video memory is going to be slow. + * + * XXX: At some point we should be allocating a backbuffer + * instead when it's time for *all* TTYs to have them. + * + * A good idea would be to only allocate a backbuffer + * *if* we switched to some TTY and deallocate + * that backbuffer when switching away from that TTY. + * + * The first thing that comes to mind when thinking + * about this idea is loosing our text when we switch + * back out. To rectify this, we could buffer chars + * which would take less memory than keeping the whole + * backbuffer (holds pixels i.e uint32_t). + * + * This can perhaps be done by some internal flag which + * indicates that kmalloc() is usable and chars can + * be buffered. Once we switch back, just allocate + * a new backbuffer and copy the chars back. + */ + tty->fbdev = fbdev_get_front(); + tty->t_oflag = (OPOST | ORBUF); + tty->tab_width = DEFAULT_TAB_WIDTH; + tty->fg = 0x808080; + tty->bg = 0x000000; + tty->t_ws_xpixel = tty->fbdev.width; + tty->t_ws_ypixel = tty->fbdev.height; + tty->t_ws_row = tty->fbdev.height / FONT_HEIGHT; + tty->t_ws_col = tty->fbdev.width / FONT_WIDTH; + +} + +void +tty_attach(struct tty *tty) +{ + TAILQ_INSERT_TAIL(&tty_list, tty, link); + tty_draw_cursor(tty, false); +} + +void +tty_init(void) +{ + TAILQ_INIT(&tty_list); /* Ensure the TTY list is usable */ +} diff --git a/sys/kern/tty_subr.c b/sys/kern/tty_subr.c new file mode 100644 index 0000000..4c8405e --- /dev/null +++ b/sys/kern/tty_subr.c @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2023 Ian Marco Moffett and the VegaOS team. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of VegaOS nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* $Id$ */ + +#include + +/* + * Pushes a char to the TTY + * ring buffer. + * + * Call with TTY locked. + */ +void +tty_push_char(struct tty *tty, int c) +{ + struct tty_ring *ring; + + ring = &tty->ring; + + /* + * If our ring is full, it should + * be flushed as soon as possible. + * + * XXX: ring->len will be reset by tty_flush() + * so there is no need to do it here. + */ + if (ring->len >= LINE_RING_SIZE) { + tty_flush(tty); + } + + ring->buf[ring->len++] = c; +} -- cgit v1.2.3