From 19ae642bf33f5c263b0f26971fb24b859853ad9d Mon Sep 17 00:00:00 2001 From: John Tsiombikas Date: Tue, 13 Aug 2024 03:03:52 +0300 Subject: [PATCH] started organizing console, rudimentary printf, initial device structure --- kern/src/con.c | 130 ++++++------------------------------------ kern/src/con.h | 21 +------ kern/src/config.h | 9 +++ kern/src/dbg.c | 6 ++ kern/src/dbg.h | 6 ++ kern/src/dev.c | 6 ++ kern/src/dev.h | 17 ++++++ kern/src/file.h | 23 ++++++++ kern/src/fs.h | 15 +++++ kern/src/libc/stdarg.h | 11 ++++ kern/src/libc/stdio.c | 146 ++++++++++++++++++++++++++++++++++++++++++++++++ kern/src/libc/stdio.h | 10 ++++ kern/src/libc/string.c | 8 +++ kern/src/libc/string.h | 2 + kern/src/main.c | 11 +++- kern/src/ser.c | 6 ++ kern/src/ser.h | 6 ++ kern/src/vid.c | 46 +++++++++++++-- kern/src/vid.h | 8 +-- 19 files changed, 348 insertions(+), 139 deletions(-) create mode 100644 kern/src/config.h create mode 100644 kern/src/dbg.c create mode 100644 kern/src/dbg.h create mode 100644 kern/src/dev.c create mode 100644 kern/src/dev.h create mode 100644 kern/src/file.h create mode 100644 kern/src/fs.h create mode 100644 kern/src/libc/stdarg.h create mode 100644 kern/src/libc/stdio.c create mode 100644 kern/src/libc/stdio.h create mode 100644 kern/src/libc/string.c create mode 100644 kern/src/ser.c create mode 100644 kern/src/ser.h diff --git a/kern/src/con.c b/kern/src/con.c index 8b5a244..633462e 100644 --- a/kern/src/con.c +++ b/kern/src/con.c @@ -1,126 +1,32 @@ -#if 0 -#include "con.h" - - - -#define NCOLS 80 -#define NROWS 25 - -/* must be pow2 */ -#define TEXTBUF_SIZE 256 - -static char textbuf[TEXTBUF_SIZE][NCOLS]; -static int tbuf_first, tbuf_last; +#include "config.h" -static int curx, cury, scroll; - -#define CURSTACK_SIZE 16 -static unsigned int savecur[CURSTACK_SIZE]; -static int savecur_top; - - -static void newline(void); +#include "con.h" +#include "dev.h" +#include "vid.h" +#include "dbg.h" +static struct file *devfile; void con_init(void) { - con_reset(); -} - -void con_reset(void) -{ - vga_reset(); - - curx = cury = scroll = 0; - tbuf_first = tbuf_last = 0; - memset(textbuf[0], 0, sizeof textbuf[0]); - - savecur_top = 0; -} - -void con_setcur(int x, int y) -{ - curx = x < 0 ? 0 : (x >= NCOLS ? NCOLS - 1 : x); - cury = y < 0 ? 0 : (y >= NROWS ? NROWS - 1 : y); -} - -void con_getcur(int *x, int *y) -{ - *x = curx; - *y = cury; -} - -void con_pushcur(void) -{ - if(savecur_top >= CURSTACK_SIZE) return; - - savecur[savecur_top++] = curx | (cury << 16); -} - -void con_popcur(void) -{ - if(savecur_top <= 0) return; - - savecur_top--; - curx = savecur[savecur_top] & 0xffff; - cury = savecur[savecur_top] >> 16; + if(!(devfile = dev_open(CONDEV, 0, O_RDWR))) { + panic("can't open console device %d,%d\n", CONDEV, 0); + } } -void con_putchar(int c) +void con_printf(const char *fmt, ...) { - switch(c) { - case '\t': - curx = (curx + 8) & 0xfffffff8; - if(curx >= NCOLS) { - newline(); - } - break; - - case '\r': - curx = 0; - break; - - case '\n': - newline(); - break; - - case '\b': - if(curx > 0) { - textbuf[tbuf_last][--curx] = 0; - vga_drawchar(curx, cury, 0); - } - break; - - default: - textbuf[tbuf_last][curx] = c; - vga_drawchar(curx, cury, c); - if(++curx >= NCOLS) { - newline(); - } - break; - } - - if(cury >= NROWS) { - cury--; - vga_scroll(++scroll); - vga_clearline(NROWS - 1); + /* TODO */ + while(*fmt) { + con_putchar(*fmt++); } - - vid_set_cursor(curx, cury); } -static void newline(void) +void con_putchar(int c) { - int num; - - curx = 0; - cury++; - - num = (tbuf_last + 1) & (TEXTBUF_SIZE - 1); - - if(tbuf_last == tbuf_first) { - tbuf_first = num; + if(devfile) { + devfile->dev->fop->write(devfile, &c, 1); + } else { + vid_putchar(c); } - tbuf_last = num; } -#endif diff --git a/kern/src/con.h b/kern/src/con.h index b5f8545..e6eee5f 100644 --- a/kern/src/con.h +++ b/kern/src/con.h @@ -1,24 +1,9 @@ #ifndef CON_H_ #define CON_H_ -struct console { - void (*clear)(void*); - void (*putc)(void*, int c); - - void *data; -}; - -void con_init(struct console *con); - -void con_reset(struct console *con); -void con_setcolor(struct console *con, int fg, int bg); - -void con_setcur(struct console *con, int x, int y); -void con_getcur(struct console *con, int *x, int *y); -void con_pushcur(struct console *con); -void con_popcur(struct console *con); - -void con_putchar(struct console *con, int c); +void con_init(void); +void con_printf(const char *fmt, ...); +void con_putchar(int c); #endif /* CON_H_ */ diff --git a/kern/src/config.h b/kern/src/config.h new file mode 100644 index 0000000..d46832b --- /dev/null +++ b/kern/src/config.h @@ -0,0 +1,9 @@ +#ifndef CONFIG_H_ +#define CONFIG_H_ + +#define VERSTR "v0.0" + +/* CONDEV: which device to use for the kernel console (DEV_VID or DEV_SER) */ +#define CONDEV DEV_VID + +#endif /* CONFIG_H_ */ diff --git a/kern/src/dbg.c b/kern/src/dbg.c new file mode 100644 index 0000000..ad4c57a --- /dev/null +++ b/kern/src/dbg.c @@ -0,0 +1,6 @@ +#include +#include "dbg.h" + +void panic(const char *fmt, ...) +{ +} diff --git a/kern/src/dbg.h b/kern/src/dbg.h new file mode 100644 index 0000000..acf7d3e --- /dev/null +++ b/kern/src/dbg.h @@ -0,0 +1,6 @@ +#ifndef DBG_H_ +#define DBG_H_ + +void panic(const char *fmt, ...); + +#endif /* DBG_H_ */ diff --git a/kern/src/dev.c b/kern/src/dev.c new file mode 100644 index 0000000..e0635cf --- /dev/null +++ b/kern/src/dev.c @@ -0,0 +1,6 @@ +#include "dev.h" + +struct file *dev_open(int major, int minor, unsigned int flags) +{ + return 0; /* TODO */ +} diff --git a/kern/src/dev.h b/kern/src/dev.h new file mode 100644 index 0000000..1f5a883 --- /dev/null +++ b/kern/src/dev.h @@ -0,0 +1,17 @@ +#ifndef DEV_H_ +#define DEV_H_ + +#include "file.h" + +struct device { + struct fileops *fop; +}; + +#define MAX_DEVICES 32 + +#define DEV_VID 0 +#define DEV_SER 1 + +struct file *dev_open(int major, int minor, unsigned int flags); + +#endif /* DEV_H_ */ diff --git a/kern/src/file.h b/kern/src/file.h new file mode 100644 index 0000000..4bff2c6 --- /dev/null +++ b/kern/src/file.h @@ -0,0 +1,23 @@ +#ifndef FILE_H_ +#define FILE_H_ + +#include "fs.h" + +struct device; + +struct file { + int type; + struct device *dev; + int cur_rd, cur_wr; +}; + +struct fileops { + struct file *(*open)(int inum, unsigned int flags); + int (*close)(struct file*); + int (*read)(struct file*, void*, int); + int (*write)(struct file*, void*, int); + int (*ioctl)(struct file*, int, void*, int); +}; + + +#endif /* FILE_H_ */ diff --git a/kern/src/fs.h b/kern/src/fs.h new file mode 100644 index 0000000..9ec56f9 --- /dev/null +++ b/kern/src/fs.h @@ -0,0 +1,15 @@ +#ifndef FS_H_ +#define FS_H_ + +#define O_RD 1 +#define O_WR 2 +#define O_RDWR (O_RD | O_WR) + +struct inode { + int inum; + int mode; + int user, group; + int dev_major, dev_minor; +}; + +#endif /* FS_H_ */ diff --git a/kern/src/libc/stdarg.h b/kern/src/libc/stdarg.h new file mode 100644 index 0000000..bb589db --- /dev/null +++ b/kern/src/libc/stdarg.h @@ -0,0 +1,11 @@ +#ifndef STDARG_H_ +#define STDARG_H_ + +typedef char *va_list; + +#define va_start(ap, last) ((ap) = (va_list)&(last)) +#define va_arg(ap, type) ((ap) += sizeof(type), *(type*)(ap)) +#define va_end(ap) +#define va_copy(dest, src) ((dest) = (src)) + +#endif /* STDARG_H_ */ diff --git a/kern/src/libc/stdio.c b/kern/src/libc/stdio.c new file mode 100644 index 0000000..5c52d56 --- /dev/null +++ b/kern/src/libc/stdio.c @@ -0,0 +1,146 @@ +#include +#include +#include + +struct outbuf { + char *buf; + int cur, size; +}; + +#define FMT_LONG 1 +#define FMT_RALIGN 2 + +struct format { + int active; + int fwidth, fchar; + int base; + unsigned int flags; +}; + +static void reset_format(struct format *fmt); +static int intern_vprintf(struct outbuf *outbuf, const char *fmt, va_list ap); +static void wrchar(struct outbuf *outbuf, int c); +static int wrstr(struct outbuf *outbuf, struct format *fmt, const char *s); +static int wrint(struct outbuf *outbuf, struct format *fmt, long val); +static int wruint(struct outbuf *outbuf, struct format *fmt, unsigned long val); + +int printf(const char *fmt, ...) +{ + int res; + va_list ap; + + va_start(ap, fmt); + res = intern_vprintf(0, fmt, ap); + va_end(ap); + return res; +} + +static void reset_format(struct format *fmt) +{ + memset(fmt, 0, sizeof *fmt); + fmt->fchar = ' '; +} + +static int intern_vprintf(struct outbuf *outbuf, const char *fmtstr, va_list ap) +{ + int c, count = 0; + char *str; + long val; + unsigned long uval; + struct format fmt; + + reset_format(&fmt); + + while((c = *fmtstr++)) { + if(!fmt.active) { + if(c == '%') { + fmt.active = 1; + } else { + wrchar(outbuf, c); count++; + } + } else { + /* have already started a format string */ + switch(c) { + case '%': + wrchar(outbuf, '%'); count++; + reset_format(&fmt); + break; + + case 'd': + if(fmt.flags & FMT_LONG) { + val = va_arg(ap, long); + } else { + val = va_arg(ap, int); + } + count += wrint(outbuf, &fmt, val); + reset_format(&fmt); + break; + + case 'x': + fmt.base = 16; + case 'u': + if(fmt.flags & FMT_LONG) { + uval = va_arg(ap, unsigned long); + } else { + uval = va_arg(ap, unsigned int); + } + count += wrint(outbuf, &fmt, uval); + reset_format(&fmt); + break; + + case 's': + str = va_arg(ap, char*); + count += wrstr(outbuf, &fmt, str); + reset_format(&fmt); + break; + + default: + /* TODO: more format specifiers */ + reset_format(&fmt); + break; + } + } + } + + return count; +} + +static void wrchar(struct outbuf *outbuf, int c) +{ + if(outbuf && outbuf->buf) { + if(outbuf->cur < outbuf->size) { + outbuf->buf[outbuf->cur++] = c; + } + } else { + putchar(c); + } +} + +static int wrstr(struct outbuf *outbuf, struct format *fmt, const char *s) +{ + int count = 0; + int len; + + if(fmt->flags & FMT_RALIGN) { + len = strlen(s); + while(len-- < fmt->fwidth) { + wrchar(outbuf, fmt->fchar); + count++; + } + } + while(*s) { + wrchar(outbuf, *s++); + count++; + } + return count; +} + +static int wrint(struct outbuf *outbuf, struct format *fmt, long val) +{ + return 0; /* TODO */ +} + +static int wruint(struct outbuf *outbuf, struct format *fmt, unsigned long val) +{ + return 0; /* TODO */ +} diff --git a/kern/src/libc/stdio.h b/kern/src/libc/stdio.h new file mode 100644 index 0000000..075715c --- /dev/null +++ b/kern/src/libc/stdio.h @@ -0,0 +1,10 @@ +#ifndef STDIO_H_ +#define STDIO_H_ + +#include "con.h" + +#define putchar(c) con_putchar(c) + +int printf(const char *fmt, ...); + +#endif /* STDIO_H_ */ diff --git a/kern/src/libc/string.c b/kern/src/libc/string.c new file mode 100644 index 0000000..8b5325a --- /dev/null +++ b/kern/src/libc/string.c @@ -0,0 +1,8 @@ +#include "string.h" + +int strlen(const char *s) +{ + const char *end = s; + while(*end) end++; + return end - s; +} diff --git a/kern/src/libc/string.h b/kern/src/libc/string.h index 46dd696..4c4df55 100644 --- a/kern/src/libc/string.h +++ b/kern/src/libc/string.h @@ -6,4 +6,6 @@ void *memset(void *s, int c, size_t n); void __far *fmemset(void __far *s, int c, size_t n); +int strlen(const char *s); + #endif /* STRING_H_ */ diff --git a/kern/src/main.c b/kern/src/main.c index cc3cd14..b59e371 100644 --- a/kern/src/main.c +++ b/kern/src/main.c @@ -1,9 +1,18 @@ +#include "config.h" + +#include #include "intr.h" #include "vid.h" +#include "ser.h" +#include "con.h" void kmain(void) { vid_init(); - vid_text(0, 0, "hello!", VID_ATTR(LTRED, BLACK)); + ser_init(); + con_init(); + + printf("eightysix kernel %s\n", VERSTR); + init_intr(); } diff --git a/kern/src/ser.c b/kern/src/ser.c new file mode 100644 index 0000000..2c6fd74 --- /dev/null +++ b/kern/src/ser.c @@ -0,0 +1,6 @@ +#include "ser.h" + +int ser_init(void) +{ + return -1; /* TODO */ +} diff --git a/kern/src/ser.h b/kern/src/ser.h new file mode 100644 index 0000000..0a1f418 --- /dev/null +++ b/kern/src/ser.h @@ -0,0 +1,6 @@ +#ifndef SER_H_ +#define SER_H_ + +int ser_init(void); + +#endif /* SER_H_ */ diff --git a/kern/src/vid.c b/kern/src/vid.c index 25c7cf1..5cbe7b2 100644 --- a/kern/src/vid.c +++ b/kern/src/vid.c @@ -17,8 +17,6 @@ static int detect_egainfo(void); static void detect_eqlist(void); static void crtc_write(int reg, unsigned char val); -//struct console con_vid = { con_clear, con_putc, 0 }; - static uint16_t __far *vmem; static int iobase; @@ -27,6 +25,9 @@ static int cur_x, cur_y; static int cur_scroll; static int mono; +int vid_type; + + void vid_init(void) { detect_video(); @@ -145,7 +146,7 @@ static void detect_eqlist(void) void vid_reset(void) { - vid_fgcolor(WHITE); + vid_fgcolor(LTGREY); vid_bgcolor(BLACK); vid_scroll(0); vid_setcursor(0, 0); @@ -209,7 +210,7 @@ void vid_bgcolor(int color) cur_attr = (cur_attr & 0x0f) | (color << 4); } -void vid_glyph(int x, int y, int c, int attr) +void vid_char(int x, int y, int c, int attr) { uint16_t __far *ptr; uint16_t val = c | (attr << 8); @@ -249,6 +250,43 @@ void vid_text(int x, int y, const char *s, int attr) } } +void vid_putchar(int c) +{ + int x; + + switch(c) { + case '\r': + vid_setcursor(0, cur_y); + break; + + case '\n': + if(cur_y >= cur_scroll + 25) { + vid_scroll(cur_scroll + 1); + vid_setcursor(0, cur_y); + } else { + vid_setcursor(0, cur_y + 1); + } + break; + + case '\t': + x = (cur_x + 8) & 0xf8; + if(x >= 80) { + vid_putchar('\n'); + } else { + vid_setcursor(x, cur_y); + } + break; + + default: + vid_char(cur_x, cur_y, c, cur_attr); + if(cur_x + 1 >= 80) { + vid_putchar('\n'); + } else { + vid_setcursor(cur_x + 1, cur_y); + } + } +} + static void crtc_write(int reg, unsigned char val) { outp(CRTC_ADDR_PORT, reg); diff --git a/kern/src/vid.h b/kern/src/vid.h index 6b3d678..e118ead 100644 --- a/kern/src/vid.h +++ b/kern/src/vid.h @@ -2,7 +2,6 @@ #define VID_H_ #include -#include "con.h" enum { BLACK, BLUE, GREEN, CYAN, RED, MAGENTA, BROWN, LTGREY, @@ -13,8 +12,7 @@ enum { VID_UNK, VID_MDA, VID_CGA, VID_EGA, VID_PGA, VID_MCGA, VID_VGA }; #define VID_ATTR(fg, bg) (((uint8_t)(bg) << 4) | ((uint8_t)(fg))) -extern struct console con_vid; -int vid_type; +extern int vid_type; void vid_init(void); void vid_reset(void); @@ -27,7 +25,9 @@ void vid_setcursor(int x, int y); void vid_fgcolor(int color); void vid_bgcolor(int color); -void vid_glyph(int x, int y, int c, int attr); +void vid_char(int x, int y, int c, int attr); void vid_text(int x, int y, const char *s, int attr); +void vid_putchar(int c); + #endif /* VID_H_ */ -- 1.7.10.4