vga text output and libc expansion
authorJohn Tsiombikas <nuclear@member.fsf.org>
Tue, 8 Jun 2021 14:27:53 +0000 (17:27 +0300)
committerJohn Tsiombikas <nuclear@member.fsf.org>
Tue, 8 Jun 2021 14:27:53 +0000 (17:27 +0300)
16 files changed:
sys1/kern/src/asmutil.h [new file with mode: 0644]
sys1/kern/src/libc/ctype.c [new file with mode: 0644]
sys1/kern/src/libc/ctype.h [new file with mode: 0644]
sys1/kern/src/libc/limits.h [new file with mode: 0644]
sys1/kern/src/libc/stdarg.h [new file with mode: 0644]
sys1/kern/src/libc/stddef.h [new file with mode: 0644]
sys1/kern/src/libc/stdio.c [new file with mode: 0644]
sys1/kern/src/libc/stdio.h [new file with mode: 0644]
sys1/kern/src/libc/stdlib.c [new file with mode: 0644]
sys1/kern/src/libc/stdlib.h
sys1/kern/src/libc/string.c
sys1/kern/src/libc/string.h
sys1/kern/src/main.c
sys1/kern/src/start.asm
sys1/kern/src/vga.c [new file with mode: 0644]
sys1/kern/src/vga.h

diff --git a/sys1/kern/src/asmutil.h b/sys1/kern/src/asmutil.h
new file mode 100644 (file)
index 0000000..fb852a1
--- /dev/null
@@ -0,0 +1,44 @@
+#ifndef ASMUTIL_H_
+#define ASMUTIL_H_
+
+#include <stdint.h>
+
+/* inline assembly utility macros */
+
+#define enable_intr() asm volatile("sti")
+#define disable_intr() asm volatile("cli")
+
+#define set_intr_state(en) \
+       do { if(en) enable_intr(); else disable_intr(); } while(0)
+
+static inline int get_intr_state(void)
+{
+       int res;
+       asm volatile (
+               "\r\tpushf"
+               "\r\tpop %0"
+               : "=r"(res));
+       return (res >> 9) & 1;  /* IF is bit 9 of eflags */
+}
+
+#define outp(port, val) \
+       asm volatile("out %%al, %%dx" :: "d"(port), "a"((unsigned char)val))
+#define outp16(port, val) \
+       asm volatile("out %%ax, %%dx" :: "d"(port), "a"((unsigned short)val))
+
+static inline uint8_t inp(int port)
+{
+       uint8_t res;
+       asm volatile("in %%dx, %%al" : "=a"(res) : "d"(port));
+       return res;
+}
+
+static inline uint16_t inp16(int port)
+{
+       uint16_t res;
+       asm volatile("in %%dx, %%ax" : "=a"(res) : "d"(port));
+       return res;
+}
+
+
+#endif /* ASMUTIL_H_ */
diff --git a/sys1/kern/src/libc/ctype.c b/sys1/kern/src/libc/ctype.c
new file mode 100644 (file)
index 0000000..f720566
--- /dev/null
@@ -0,0 +1,56 @@
+#include "ctype.h"
+
+int isalnum(int c)
+{
+       return isalpha(c) || isdigit(c);
+}
+
+int isalpha(int c)
+{
+       return isupper(c) || islower(c);
+}
+
+int isblank(int c)
+{
+       return c == ' ' || c == '\t';
+}
+
+int isdigit(int c)
+{
+       return c >= '0' && c <= '9';
+}
+
+int isupper(int c)
+{
+       return c >= 'A' && c <= 'Z';
+}
+
+int islower(int c)
+{
+       return c >= 'a' && c <= 'z';
+}
+
+int isgraph(int c)
+{
+       return c > ' ' && c <= '~';
+}
+
+int isprint(int c)
+{
+       return isgraph(c) || c == ' ';
+}
+
+int isspace(int c)
+{
+       return isblank(c) || c == '\f' || c == '\n' || c == '\r' || c == '\v';
+}
+
+int toupper(int c)
+{
+       return islower(c) ? (c + ('A' - 'a')) : c;
+}
+
+int tolower(int c)
+{
+       return isupper(c) ? (c - ('A' - 'a')) : c;
+}
diff --git a/sys1/kern/src/libc/ctype.h b/sys1/kern/src/libc/ctype.h
new file mode 100644 (file)
index 0000000..5b010d4
--- /dev/null
@@ -0,0 +1,17 @@
+#ifndef CTYPE_H_
+#define CTYPE_H_
+
+int isalnum(int c);
+int isalpha(int c);
+#define isascii(c)     ((c) < 128)
+int isblank(int c);
+int isdigit(int c);
+int isupper(int c);
+int islower(int c);
+int isprint(int c);
+int isspace(int c);
+
+int toupper(int c);
+int tolower(int c);
+
+#endif /* CTYPE_H_ */
diff --git a/sys1/kern/src/libc/limits.h b/sys1/kern/src/libc/limits.h
new file mode 100644 (file)
index 0000000..33dfd5c
--- /dev/null
@@ -0,0 +1,19 @@
+#ifndef KLIBC_LIMITS_H_
+#define KLIBC_LIMITS_H_
+
+#define CHAR_BIT       8
+
+#define SHRT_MIN       (-32768)
+#define SHRT_MAX       32767
+#define INT_MIN                (-2147483648)
+#define INT_MAX                2147483647
+#define LONG_MIN       (-2147483648)
+#define LONG_MAX       2147483647
+
+#define USHRT_MAX      65535
+#define UINT_MAX       0xffffffff
+#define ULONG_MAX      0xffffffff
+
+#define PATH_MAX       256
+
+#endif /* KLIBC_LIMITS_H_ */
diff --git a/sys1/kern/src/libc/stdarg.h b/sys1/kern/src/libc/stdarg.h
new file mode 100644 (file)
index 0000000..f870438
--- /dev/null
@@ -0,0 +1,12 @@
+#ifndef STDARG_H_
+#define STDARG_H_
+
+/* Assumes that arguments are passed on the stack 4-byte aligned */
+
+typedef int* va_list;
+
+#define va_start(ap, last)     ((ap) = (int*)&(last) + 1)
+#define va_arg(ap, type)       (*(type*)(ap)++)
+#define va_end(ap)
+
+#endif /* STDARG_H_ */
diff --git a/sys1/kern/src/libc/stddef.h b/sys1/kern/src/libc/stddef.h
new file mode 100644 (file)
index 0000000..629ed8b
--- /dev/null
@@ -0,0 +1,11 @@
+#ifndef KLIBC_STDDEF_H_
+#define KLIBC_STDDEF_H_
+
+#include <stdint.h>
+
+typedef int32_t ssize_t;
+typedef uint32_t size_t;
+
+typedef uint32_t intptr_t;
+
+#endif /* KLIBC_STDDEF_H_ */
diff --git a/sys1/kern/src/libc/stdio.c b/sys1/kern/src/libc/stdio.c
new file mode 100644 (file)
index 0000000..2035cf8
--- /dev/null
@@ -0,0 +1,320 @@
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+
+enum {
+       OUT_DEF,
+       OUT_BUF
+};
+
+static int intern_printf(int out, char *buf, size_t sz, const char *fmt, va_list ap);
+static void bwrite(int out, char *buf, size_t buf_sz, char *str, int sz);
+/*static int readchar(const char *str, FILE *fp);*/
+
+int putchar(int c)
+{
+       /*con_putchar(c);*/
+       return c;
+}
+
+int puts(const char *s)
+{
+       while(*s) {
+               putchar(*s++);
+       }
+       putchar('\n');
+       return 0;
+}
+
+/* -- printf and friends -- */
+
+int printf(const char *fmt, ...)
+{
+       int res;
+       va_list ap;
+
+       va_start(ap, fmt);
+       res = intern_printf(OUT_DEF, 0, 0, fmt, ap);
+       va_end(ap);
+       return res;
+}
+
+int vprintf(const char *fmt, va_list ap)
+{
+       return intern_printf(OUT_DEF, 0, 0, fmt, ap);
+}
+
+int sprintf(char *buf, const char *fmt, ...)
+{
+       int res;
+       va_list ap;
+
+       va_start(ap, fmt);
+       res = intern_printf(OUT_BUF, buf, 0, fmt, ap);
+       va_end(ap);
+       return res;
+}
+
+int vsprintf(char *buf, const char *fmt, va_list ap)
+{
+       return intern_printf(OUT_BUF, buf, 0, fmt, ap);
+}
+
+int snprintf(char *buf, size_t sz, const char *fmt, ...)
+{
+       int res;
+       va_list ap;
+
+       va_start(ap, fmt);
+       res = intern_printf(OUT_BUF, buf, sz, fmt, ap);
+       va_end(ap);
+       return res;
+}
+
+int vsnprintf(char *buf, size_t sz, const char *fmt, va_list ap)
+{
+       return intern_printf(OUT_BUF, buf, sz, fmt, ap);
+}
+
+/* intern_printf provides all the functionality needed by all the printf
+ * variants.
+ * - buf: optional buffer onto which the formatted results are written. If null
+ *   then the output goes to the terminal through putchar calls. This is used
+ *   by the (v)sprintf variants which write to an array of char.
+ * - sz: optional maximum size of the output, 0 means unlimited. This is used
+ *   by the (v)snprintf variants to avoid buffer overflows.
+ * The rest are obvious, format string and variable argument list.
+ */
+static char *convc = "dioxXucsfeEgGpn%";
+
+#define IS_CONV(c)     strchr(convc, c)
+
+#define BUF(x) ((x) ? (x) + cnum : (x))
+#define SZ(x)  ((x) ? (x) - cnum : (x))
+
+static int intern_printf(int out, char *buf, size_t sz, const char *fmt, va_list ap)
+{
+       char conv_buf[32];
+       char *str;
+       int i, slen;
+       const char *fstart = 0;
+
+       /* state */
+       int cnum = 0;
+       int base = 10;
+       int alt = 0;
+       int fwidth = 0;
+       int padc = ' ';
+       int sign = 0;
+       int left_align = 0;
+       int hex_caps = 0;
+       int unsig = 0;
+       int num, unum;
+
+       while(*fmt) {
+               if(*fmt == '%') {
+                       fstart = fmt++;
+                       continue;
+               }
+
+               if(fstart) {
+                       if(IS_CONV(*fmt)) {
+                               switch(*fmt) {
+                               case 'X':
+                                       hex_caps = 1;
+
+                               case 'x':
+                               case 'p':
+                                       base = 16;
+
+                                       if(alt) {
+                                               bwrite(out, BUF(buf), SZ(sz), "0x", 2);
+                                               cnum += 2;
+                                       }
+
+                               case 'u':
+                                       unsig = 1;
+
+                                       if(0) {
+                               case 'o':
+                                               base = 8;
+
+                                               if(alt) {
+                                                       bwrite(out, BUF(buf), SZ(sz), "0", 1);
+                                                       cnum++;
+                                               }
+                                       }
+
+                               case 'd':
+                               case 'i':
+                                       if(unsig) {
+                                               unum = va_arg(ap, unsigned int);
+                                               utoa(unum, conv_buf, base);
+                                       } else {
+                                               num = va_arg(ap, int);
+                                               itoa(num, conv_buf, base);
+                                       }
+                                       if(hex_caps) {
+                                               for(i=0; conv_buf[i]; i++) {
+                                                       conv_buf[i] = toupper(conv_buf[i]);
+                                               }
+                                       }
+
+                                       slen = strlen(conv_buf);
+
+                                       if(left_align) {
+                                               if(!unsig && sign && num >= 0) {
+                                                       bwrite(out, BUF(buf), SZ(sz), "+", 1);
+                                                       cnum++;
+                                               }
+                                               bwrite(out, BUF(buf), SZ(sz), conv_buf, slen);
+                                               cnum += slen;
+                                               padc = ' ';
+                                       }
+                                       for(i=slen; i<fwidth; i++) {
+                                               bwrite(out, BUF(buf), SZ(sz), (char*)&padc, 1);
+                                               cnum++;
+                                       }
+                                       if(!left_align) {
+                                               if(!unsig && sign && num >= 0) {
+                                                       bwrite(out, BUF(buf), SZ(sz), "+", 1);
+                                                       cnum++;
+                                               }
+                                               bwrite(out, BUF(buf), SZ(sz), conv_buf, slen);
+                                               cnum += slen;
+                                       }
+                                       break;
+
+                               case 'c':
+                                       {
+                                               char c = va_arg(ap, int);
+                                               bwrite(out, BUF(buf), SZ(sz), &c, 1);
+                                               cnum++;
+                                       }
+                                       break;
+
+                               case 's':
+                                       str = va_arg(ap, char*);
+                                       slen = strlen(str);
+
+                                       if(left_align) {
+                                               bwrite(out, BUF(buf), SZ(sz), str, slen);
+                                               cnum += slen;
+                                               padc = ' ';
+                                       }
+                                       for(i=slen; i<fwidth; i++) {
+                                               bwrite(out, BUF(buf), SZ(sz), (char*)&padc, 1);
+                                               cnum++;
+                                       }
+                                       if(!left_align) {
+                                               bwrite(out, BUF(buf), SZ(sz), str, slen);
+                                               cnum += slen;
+                                       }
+                                       break;
+
+                               case 'n':
+                                       *va_arg(ap, int*) = cnum;
+                                       break;
+
+                               default:
+                                       break;
+                               }
+
+                               /* restore default conversion state */
+                               base = 10;
+                               alt = 0;
+                               fwidth = 0;
+                               padc = ' ';
+                               hex_caps = 0;
+
+                               fstart = 0;
+                               fmt++;
+                       } else {
+                               switch(*fmt) {
+                               case '#':
+                                       alt = 1;
+                                       break;
+
+                               case '+':
+                                       sign = 1;
+                                       break;
+
+                               case '-':
+                                       left_align = 1;
+                                       break;
+
+                               case 'l':
+                               case 'L':
+                                       break;
+
+                               case '0':
+                                       padc = '0';
+                                       break;
+
+                               default:
+                                       if(isdigit(*fmt)) {
+                                               const char *fw = fmt;
+                                               while(*fmt && isdigit(*fmt)) fmt++;
+
+                                               fwidth = atoi(fw);
+                                               continue;
+                                       }
+                               }
+                               fmt++;
+                       }
+               } else {
+                       bwrite(out, BUF(buf), SZ(sz), (char*)fmt++, 1);
+                       cnum++;
+               }
+       }
+
+       return cnum;
+}
+
+
+/* bwrite is called by intern_printf to transparently handle writing into a
+ * buffer or to the terminal
+ */
+static void bwrite(int out, char *buf, size_t buf_sz, char *str, int sz)
+{
+       int i;
+
+       if(out == OUT_BUF) {
+               if(buf_sz && buf_sz <= sz) sz = buf_sz;
+               buf[sz] = 0;
+               memcpy(buf, str, sz);
+       } else {
+               switch(out) {
+               case OUT_DEF:
+                       for(i=0; i<sz; i++) {
+                               putchar(*str++);
+                       }
+                       break;
+
+               default:
+                       break;
+               }
+       }
+}
+
+/*
+static int readchar(const char *str, FILE *fp)
+{
+       static const char *orig_str;
+       static const char *sptr;
+
+       if(str) {
+               if(str == orig_str) {
+                       if(!*sptr) return -1;
+                       return *sptr++;
+               } else {
+                       orig_str = sptr = str;
+                       return readchar(str, fp);
+               }
+       } else {
+               return fgetc(fp);
+       }
+
+       return -1;
+}
+*/
diff --git a/sys1/kern/src/libc/stdio.h b/sys1/kern/src/libc/stdio.h
new file mode 100644 (file)
index 0000000..77a431f
--- /dev/null
@@ -0,0 +1,24 @@
+#ifndef STDIO_H_
+#define STDIO_H_
+
+#include <stdlib.h>
+#include <stdarg.h>
+
+int putchar(int c);
+int puts(const char *s);
+
+int printf(const char *fmt, ...);
+int vprintf(const char *fmt, va_list ap);
+
+int sprintf(char *buf, const char *fmt, ...);
+int vsprintf(char *buf, const char *fmt, va_list ap);
+
+int snprintf(char *buf, size_t sz, const char *fmt, ...);
+int vsnprintf(char *buf, size_t sz, const char *fmt, va_list ap);
+
+/* TODO
+int sscanf(const char *str, const char *fmt, ...);
+int vsscanf(const char *ptr, const char *fmt, va_list ap);
+*/
+
+#endif /* STDIO_H_ */
diff --git a/sys1/kern/src/libc/stdlib.c b/sys1/kern/src/libc/stdlib.c
new file mode 100644 (file)
index 0000000..859372f
--- /dev/null
@@ -0,0 +1,193 @@
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <limits.h>
+
+int atoi(const char *str)
+{
+       return strtol(str, 0, 10);
+}
+
+long atol(const char *str)
+{
+       return strtol(str, 0, 10);
+}
+
+long strtol(const char *str, char **endp, int base)
+{
+       long acc = 0;
+       int sign = 1;
+       int valid = 0;
+       const char *start = str;
+
+       while(isspace(*str)) str++;
+
+       if(base == 0) {
+               if(str[0] == '0') {
+                       if(str[1] == 'x' || str[1] == 'X') {
+                               base = 16;
+                       } else {
+                               base = 8;
+                       }
+               } else {
+                       base = 10;
+               }
+       }
+
+       if(*str == '+') {
+               str++;
+       } else if(*str == '-') {
+               sign = -1;
+               str++;
+       }
+
+       while(*str) {
+               long val = LONG_MAX;
+               char c = tolower(*str);
+
+               if(isdigit(c)) {
+                       val = *str - '0';
+               } else if(c >= 'a' && c <= 'f') {
+                       val = 10 + c - 'a';
+               } else {
+                       break;
+               }
+               if(val >= base) {
+                       break;
+               }
+               valid = 1;
+
+               acc = acc * base + val;
+               str++;
+       }
+
+       if(endp) {
+               *endp = (char*)(valid ? str : start);
+       }
+
+       return sign > 0 ? acc : -acc;
+}
+
+void itoa(int val, char *buf, int base)
+{
+       static char rbuf[16];
+       char *ptr = rbuf;
+       int neg = 0;
+
+       if(val < 0) {
+               neg = 1;
+               val = -val;
+       }
+
+       if(val == 0) {
+               *ptr++ = '0';
+       }
+
+       while(val) {
+               int digit = val % base;
+               *ptr++ = digit < 10 ? (digit + '0') : (digit - 10 + 'a');
+               val /= base;
+       }
+
+       if(neg) {
+               *ptr++ = '-';
+       }
+
+       ptr--;
+
+       while(ptr >= rbuf) {
+               *buf++ = *ptr--;
+       }
+       *buf = 0;
+}
+
+void utoa(unsigned int val, char *buf, int base)
+{
+       static char rbuf[16];
+       char *ptr = rbuf;
+
+       if(val == 0) {
+               *ptr++ = '0';
+       }
+
+       while(val) {
+               unsigned int digit = val % base;
+               *ptr++ = digit < 10 ? (digit + '0') : (digit - 10 + 'a');
+               val /= base;
+       }
+
+       ptr--;
+
+       while(ptr >= rbuf) {
+               *buf++ = *ptr--;
+       }
+       *buf = 0;
+}
+
+#define QSORT_THRESHOLD        4
+#define ITEM(idx)      ((char*)arr + (idx) * itemsz)
+
+#define SWAP(p, q) \
+       do { \
+               int nn = itemsz; \
+               char *pp = (p); \
+               char *qq = (q); \
+               do { \
+                       char tmp = *pp; \
+                       *pp++ = *qq; \
+                       *qq++ = tmp; \
+               } while(--nn > 0); \
+       } while(0)
+
+static void ins_sort(void *arr, size_t count, size_t itemsz, int (*cmp)(const void*, const void*))
+{
+       int i;
+       char *it, *a, *b;
+
+       if(count <= 1) return;
+
+       it = (char*)arr + itemsz;
+       for(i=1; i<count; i++) {
+               a = it;
+               it += itemsz;
+               while(a > (char*)arr && cmp(a, (b = a - itemsz)) < 0) {
+                       SWAP(a, b);
+                       a -= itemsz;
+               }
+       }
+}
+
+void qsort(void *arr, size_t count, size_t itemsz, int (*cmp)(const void*, const void*))
+{
+       char *ma, *mb, *mc, *left, *right;
+       size_t sepidx, nleft, nright;
+
+       if(count <= 1) return;
+
+       if(count < QSORT_THRESHOLD) {
+               ins_sort(arr, count, itemsz, cmp);
+               return;
+       }
+
+       ma = arr;
+       mb = ITEM(count / 2);
+       mc = ITEM(count - 1);
+       if(cmp(ma, mb) < 0) SWAP(ma, mb);
+       if(cmp(mc, ma) < 0) SWAP(mc, ma);
+
+       left = ma + itemsz;
+       right = mc - itemsz;
+       for(;;) {
+               while(cmp(left, ma) < 0) left += itemsz;
+               while(cmp(ma, right) < 0) right -= itemsz;
+               if(left >= right) break;
+               SWAP(left, right);
+       }
+       SWAP(ma, right);
+       sepidx = (right - (char*)arr) / itemsz;
+       nleft = sepidx;
+       nright = count - nleft - 1;
+
+       qsort(ma, nleft, itemsz, cmp);
+       qsort(right + itemsz, nright, itemsz, cmp);
+}
index dfd634f..4c173c6 100644 (file)
@@ -1,7 +1,23 @@
 #ifndef KLIBC_STDLIB_H_
 #define KLIBC_STDLIB_H_
 
-typedef int ssize_t;
-typedef unsigned int size_t;
+#include <stddef.h>
+
+#define abs(x) __builtin_abs(x)
+
+int atoi(const char *str);
+long atol(const char *str);
+long strtol(const char *str, char **endp, int base);
+
+void itoa(int val, char *buf, int base);
+void utoa(unsigned int val, char *buf, int base);
+
+void qsort(void *arr, size_t count, size_t size, int (*cmp)(const void*, const void*));
+
+/* defined in malloc.c */
+void *malloc(size_t sz);
+void *calloc(size_t num, size_t sz);
+void *realloc(void *ptr, size_t sz);
+void free(void *ptr);
 
 #endif /* KLIBC_STDLIB_H_ */
index 3b11896..913ffc1 100644 (file)
@@ -1,5 +1,6 @@
 #include "string.h"
 #include "stdint.h"
+#include "ctype.h"
 
 void *memset(void *dest, int val, size_t num)
 {
@@ -28,3 +29,205 @@ void *memcpy(void *dest, void *src, size_t num)
 
        return dest;
 }
+
+void *memmove(void *dest, const void *src, size_t n)
+{
+       int i;
+       char *dptr;
+       const char *sptr;
+
+       if(dest <= src) {
+               /* forward copy */
+               dptr = dest;
+               sptr = src;
+               for(i=0; i<n; i++) {
+                       *dptr++ = *sptr++;
+               }
+       } else {
+               /* backwards copy */
+               dptr = (char*)dest + n - 1;
+               sptr = (const char*)src + n - 1;
+               for(i=0; i<n; i++) {
+                       *dptr-- = *sptr--;
+               }
+       }
+
+       return dest;
+}
+
+int memcmp(void *aptr, void *bptr, size_t n)
+{
+       int i, startoffs, diff;
+       uint32_t *a32, *b32;
+       unsigned char *a = aptr;
+       unsigned char *b = bptr;
+
+       a32 = (uint32_t*)((intptr_t)(a + 3) & 0xfffffffc);
+       b32 = (uint32_t*)((intptr_t)(b + 3) & 0xfffffffc);
+
+       /* if both are aligned the same way... */
+       if((startoffs = (unsigned char*)a32 - a) == (unsigned char*)b32 - b) {
+               /* catch-up to the 32bit alignment */
+               for(i=0; i<startoffs; i++) {
+                       if((diff = *a++ - *b++) != 0 || --n <= 0) {
+                               return diff;
+                       }
+               }
+
+               /* compare 32bit at once */
+               while(n >= 4) {
+                       if(*a32 != *b32) break;
+                       a32++;
+                       b32++;
+                       n -= 4;
+               }
+
+               /* update byte pointers to contine with the tail */
+               a = (unsigned char*)a32;
+               b = (unsigned char*)b32;
+       }
+
+       /* we're here both for the tail-end of same-alignment buffers, or for the
+        * whole length of mis-aligned buffers.
+        */
+       while(n-- > 0) {
+               if((diff = *a++ - *b++) != 0) {
+                       return diff;
+               }
+       }
+       return 0;
+}
+
+size_t strlen(const char *s)
+{
+       size_t len = 0;
+       while(*s++) len++;
+       return len;
+}
+
+char *strchr(const char *s, int c)
+{
+       while(*s) {
+               if(*s == c) {
+                       return (char*)s;
+               }
+               s++;
+       }
+       return 0;
+}
+
+char *strrchr(const char *s, int c)
+{
+       const char *ptr = s;
+
+       /* find the end */
+       while(*ptr) ptr++;
+
+       /* go back checking for c */
+       while(--ptr >= s) {
+               if(*ptr == c) {
+                       return (char*)ptr;
+               }
+       }
+       return 0;
+}
+
+char *strstr(const char *str, const char *substr)
+{
+       while(*str) {
+               const char *s1 = str;
+               const char *s2 = substr;
+
+               while(*s1 && *s1 == *s2) {
+                       s1++;
+                       s2++;
+               }
+               if(!*s2) {
+                       return (char*)str;
+               }
+               str++;
+       }
+       return 0;
+}
+
+char *strcasestr(const char *str, const char *substr)
+{
+       while(*str) {
+               const char *s1 = str;
+               const char *s2 = substr;
+
+               while(*s1 && tolower(*s1) == tolower(*s2)) {
+                       s1++;
+                       s2++;
+               }
+               if(!*s2) {
+                       return (char*)str;
+               }
+               str++;
+       }
+       return 0;
+}
+
+int strcmp(const char *s1, const char *s2)
+{
+       while(*s1 && *s1 == *s2) {
+               s1++;
+               s2++;
+       }
+       return *s1 - *s2;
+}
+
+int strcasecmp(const char *s1, const char *s2)
+{
+       while(*s1 && tolower(*s1) == tolower(*s2)) {
+               s1++;
+               s2++;
+       }
+       return tolower(*s1) - tolower(*s2);
+}
+
+int strncmp(const char *s1, const char *s2, int n)
+{
+       if(n <= 0) return 0;
+
+       while(n-- > 0 && *s1 && *s2 && *s1 == *s2) {
+               s1++;
+               s2++;
+       }
+
+       if(n <= 0) return 0;
+       return *s1 - *s2;
+}
+
+int strncasecmp(const char *s1, const char *s2, int n)
+{
+       if(n <= 0) return 0;
+
+       while(n-- > 0 && *s1 && *s2 && tolower(*s1) == tolower(*s2)) {
+               s1++;
+               s2++;
+       }
+
+       if(n <= 0) return 0;
+       return tolower(*s1) - tolower(*s2);
+}
+
+char *strcpy(char *dest, const char *src)
+{
+       char *dptr = dest;
+       while((*dptr++ = *src++));
+       return dest;
+}
+
+char *strcat(char *dest, const char *src)
+{
+       strcpy(dest + strlen(dest), src);
+       return dest;
+}
+
+char *strncpy(char *dest, const char *src, int n)
+{
+       char *dptr = dest;
+       while(n-- > 0 && (*dptr++ = *src++));
+       return dest;
+}
index 8024665..be784be 100644 (file)
@@ -5,6 +5,29 @@
 
 void *memset(void *dest, int val, size_t num);
 void *memset16(void *dest, int val, size_t num);
+
 void *memcpy(void *dest, void *src, size_t num);
+void *memmove(void *dest, const void *src, size_t n);
+
+int memcmp(void *aptr, void *bptr, size_t n);
+
+size_t strlen(const char *s);
+
+char *strchr(const char *s, int c);
+char *strrchr(const char *s, int c);
+
+char *strstr(const char *str, const char *substr);
+char *strcasestr(const char *str, const char *substr);
+
+int strcmp(const char *s1, const char *s2);
+int strcasecmp(const char *s1, const char *s2);
+
+int strncmp(const char *s1, const char *s2, int n);
+int strncasecmp(const char *s1, const char *s2, int n);
+
+char *strcpy(char *dest, const char *src);
+char *strcat(char *dest, const char *src);
+
+char *strncpy(char *dest, const char *src, int n);
 
 #endif /* KLIBC_STRING_H_ */
index b89a98b..f0441e5 100644 (file)
@@ -1,22 +1,22 @@
+#include <stdio.h>
 #include <string.h>
 #include <stdint.h>
-
-void clearscr(void)
-{
-       memset((void*)0xb8000, 0, 80 * 25 * 2);
-}
+#include "vga.h"
 
 void drawtext(int x, int y, const char *s)
 {
-       uint16_t *vptr = (uint16_t*)0xb8000 + y * 80 + x;
-
        while(*s) {
-               *vptr++ = 0x0c00 | *s++;
+               vga_drawchar(x++, y, *s++);
        }
 }
 
 void kmain(void)
 {
-       clearscr();
-       drawtext(10, 5, "3sys kernel 1");
+       char buf[64];
+
+       vga_reset();
+       vga_setcolor(VGA_YELLOW | VGA_BRIGHT, VGA_BLACK);
+
+       sprintf(buf, "kmain addr: %p", (void*)kmain);
+       drawtext(10, 5, buf);
 }
index f9baf52..38219e6 100644 (file)
@@ -1,5 +1,5 @@
        bits 32
-       section .text
+       section .startup
 
        extern _bss_start
        extern _bss_size
diff --git a/sys1/kern/src/vga.c b/sys1/kern/src/vga.c
new file mode 100644 (file)
index 0000000..2967299
--- /dev/null
@@ -0,0 +1,56 @@
+#include <string.h>
+#include "vga.h"
+#include "asmutil.h"
+
+#define CRTC_ADDR_PORT 0x3d4
+#define CRTC_DATA_PORT 0x3d5
+
+/* CRTC registers */
+#define CRTC_START_H   0x0c
+#define CRTC_START_L   0x0d
+#define CRTC_CURPOS_H  0x0e
+#define CRTC_CURPOS_L  0x0f
+
+static void crtc_write(int reg, unsigned char val);
+
+static uint16_t attr = 0x0700;
+static int yoffs;
+
+void vga_setcolor(int fg, int bg)
+{
+       attr = ((bg & 7) << 12) | ((fg & 0xf) << 8);
+}
+
+void vga_setcursor(int x, int y)
+{
+       int loc = (y + yoffs) * 80 + x;
+       crtc_write(CRTC_CURPOS_H, loc >> 8);
+       crtc_write(CRTC_CURPOS_L, loc);
+}
+
+void vga_setstart(int start)
+{
+       yoffs = start;
+       crtc_write(CRTC_START_H, start >> 8);
+       crtc_write(CRTC_START_L, start);
+}
+
+void vga_reset(void)
+{
+       vga_setcolor(VGA_WHITE, VGA_BLACK);
+       vga_setstart(0);
+       vga_setcursor(0, 0);
+       memset((void*)0xb8000, 0, 80 * 25 * 2);
+}
+
+void vga_drawchar(int x, int y, int c)
+{
+       uint16_t *ptr = (uint16_t*)0xb8000 + (y + yoffs) * 80 + x;
+       *ptr = (c & 0xff) | attr;
+}
+
+static void crtc_write(int reg, unsigned char val)
+{
+       outp(CRTC_ADDR_PORT, reg);
+       outp(CRTC_DATA_PORT, val);
+}
index 19571f3..e8be27a 100644 (file)
@@ -11,9 +11,14 @@ enum {
        VGA_YELLOW,
        VGA_WHITE
 };
-#define VGA_BRIGHT     0x80
+#define VGA_BRIGHT     8
 
 void vga_setcolor(int fg, int bg);
 void vga_setcursor(int x, int y);
+void vga_setstart(int start);
+
+void vga_reset(void);
+
+void vga_drawchar(int x, int y, int c);
 
 #endif /* VGA_H_ */