moving on
authorJohn Tsiombikas <nuclear@member.fsf.org>
Tue, 13 Aug 2024 06:17:57 +0000 (09:17 +0300)
committerJohn Tsiombikas <nuclear@member.fsf.org>
Tue, 13 Aug 2024 06:17:57 +0000 (09:17 +0300)
12 files changed:
kern/src/asmutil.asm [new file with mode: 0644]
kern/src/asmutil.h
kern/src/dbg.c
kern/src/dbg.h
kern/src/libc/ctype.c [new file with mode: 0644]
kern/src/libc/ctype.h [new file with mode: 0644]
kern/src/libc/limits.h [new file with mode: 0644]
kern/src/libc/stdio.c
kern/src/libc/stdio.h
kern/src/libc/stdlib.c [new file with mode: 0644]
kern/src/libc/stdlib.h [new file with mode: 0644]
kern/src/main.c

diff --git a/kern/src/asmutil.asm b/kern/src/asmutil.asm
new file mode 100644 (file)
index 0000000..08c664e
--- /dev/null
@@ -0,0 +1,54 @@
+; utility functions
+       cpu 8086
+       bits 16
+       section .text
+
+       global getip
+getip: push bp
+       mov bp, sp
+       mov ax, [bp + 2]
+       pop bp
+       ret
+
+       global getregs
+getregs:
+       push bp
+       mov bp, sp
+
+       mov bp, [bp + 4]        ; grab regs pointer
+       mov [bp], ax
+       mov [bp + 2], bx
+       mov [bp + 4], cx
+       mov [bp + 6], dx
+       mov ax, sp
+       add ax, 6
+       mov [bp + 8], ax        ; sp before the getregs call
+       mov bx, sp
+       mov ax, [bx]
+       mov [bp + 10], ax       ; bp
+       mov [bp + 12], si
+       mov [bp + 14], di
+       pushf
+       pop ax
+       mov [bp + 16], ax       ; cflags
+       mov ax, [bx + 2]        ; caller ip
+
+       pop bp
+       ret
+
+       global getsregs
+getsregs:
+       push bp
+       mov bp, sp
+
+       mov ax, [bp + 4]
+       add ax, 8               ; point to the top of the sregs block (after ss)
+       mov sp, ax              ; point sp there
+       push ss
+       push es
+       push ds
+       push cs
+
+       mov sp, bp
+       pop bp
+       ret
index 9d5697b..1720f5a 100644 (file)
@@ -5,7 +5,9 @@
 
 struct wordregs {
        uint16_t ax, bx, cx, dx;
-       uint16_t si, di, cflag;
+       uint16_t sp, bp;
+       uint16_t si, di, flags;
+       uint16_t ip;
 } __attribute__((packed));
 
 struct byteregs {
@@ -20,7 +22,14 @@ union regs {
        struct byteregs h;
 };
 
+struct segregs {
+       uint16_t cs, ds, es, ss;
+} __attribute__((packed));
+
 void int86(int n, union regs *inregs, union regs *outregs);
+uint16_t getip(void);
+void getregs(struct wordregs *regs);
+void getsregs(struct segregs *sregs);
 
 #define FP_SEG(x)      ((uint16_t)((uint32_t)(x) >> 16))
 #define FP_OFFS(x)     ((uint16_t)(x))
@@ -28,6 +37,7 @@ void int86(int n, union regs *inregs, union regs *outregs);
 
 #define enable() asm("sti")
 #define disable() asm("cli")
+#define halt() asm("hlt")
 
 #define outp(p, v)     \
        asm volatile( \
index ad4c57a..7daf689 100644 (file)
@@ -1,6 +1,29 @@
-#include <stdarg.h>
+#include <stdio.h>
+#include <inttypes.h>
 #include "dbg.h"
+#include "asmutil.h"
 
+__attribute__((noreturn))
 void panic(const char *fmt, ...)
 {
+       va_list ap;
+       struct wordregs regs;
+       struct segregs sregs;
+
+       getregs(&regs);
+       regs.ip = getip();      /* replace ip with the caller's */
+       getsregs(&sregs);
+
+       printf("~~~~ PANIC ~~~~\n");
+
+       va_start(ap, fmt);
+       vprintf(fmt, ap);
+       va_end(ap);
+
+       printf("ax:%04x bx:%04x cx:%04x dx:%04x\n", regs.ax, regs.bx, regs.cx, regs.dx);
+       printf("bp:%04x si:%04x di:%04x flags:%04x\n", regs.bp, regs.si, regs.di, regs.flags);
+       printf("ss:sp %04x:%04x cs:ip %04x:%04x ds:%04x es:%04x\n", sregs.ss, regs.sp,
+                       sregs.cs, regs.ip, sregs.ds, sregs.es);
+
+       for(;;) halt();
 }
index acf7d3e..638f8ee 100644 (file)
@@ -1,6 +1,6 @@
 #ifndef DBG_H_
 #define DBG_H_
 
-void panic(const char *fmt, ...);
+void panic(const char *fmt, ...) __attribute__((noreturn));
 
 #endif /* DBG_H_ */
diff --git a/kern/src/libc/ctype.c b/kern/src/libc/ctype.c
new file mode 100644 (file)
index 0000000..82b7eb5
--- /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 c & ~0x20;
+}
+
+int tolower(int c)
+{
+       return c | 0x20;
+}
diff --git a/kern/src/libc/ctype.h b/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/kern/src/libc/limits.h b/kern/src/libc/limits.h
new file mode 100644 (file)
index 0000000..18d175d
--- /dev/null
@@ -0,0 +1,19 @@
+#ifndef LIMITS_H_
+#define LIMITS_H_
+
+#define CHAR_BIT       8
+
+#define SHRT_MIN       (-32768)
+#define SHRT_MAX       32767
+#define INT_MIN                (-32768)
+#define INT_MAX                32767
+#define LONG_MIN       (-2147483648)
+#define LONG_MAX       2147483647
+
+#define USHRT_MAX      65535
+#define UINT_MAX       65535
+#define ULONG_MAX      0xffffffff
+
+#define PATH_MAX       256
+
+#endif /* LIMITS_H_ */
index 5c52d56..f2a9619 100644 (file)
@@ -1,6 +1,8 @@
 #include <stdio.h>
+#include <stdlib.h>
 #include <stdarg.h>
 #include <string.h>
+#include <ctype.h>
 
 struct outbuf {
        char *buf;
@@ -35,6 +37,11 @@ int printf(const char *fmt, ...)
        return res;
 }
 
+int vprintf(const char *fmt, va_list ap)
+{
+       return intern_vprintf(0, fmt, ap);
+}
+
 static void reset_format(struct format *fmt)
 {
        memset(fmt, 0, sizeof *fmt);
@@ -84,7 +91,7 @@ static int intern_vprintf(struct outbuf *outbuf, const char *fmtstr, va_list ap)
                                } else {
                                        uval = va_arg(ap, unsigned int);
                                }
-                               count += wrint(outbuf, &fmt, uval);
+                               count += wruint(outbuf, &fmt, uval);
                                reset_format(&fmt);
                                break;
 
@@ -94,9 +101,17 @@ static int intern_vprintf(struct outbuf *outbuf, const char *fmtstr, va_list ap)
                                reset_format(&fmt);
                                break;
 
+                       case '0':
+                               if(fmt.fchar != '0') {
+                                       fmt.fchar = '0';
+                                       break;
+                               }
                        default:
-                               /* TODO: more format specifiers */
-                               reset_format(&fmt);
+                               if(isdigit(c)) {
+                                       fmt.fwidth = strtol(fmtstr - 1, (char**)&fmtstr, 10);
+                               } else {
+                                       reset_format(&fmt);
+                               }
                                break;
                        }
                }
@@ -123,7 +138,7 @@ static int wrstr(struct outbuf *outbuf, struct format *fmt, const char *s)
 
        if(fmt->flags & FMT_RALIGN) {
                len = strlen(s);
-               while(len-- < fmt->fwidth) {
+               while(len < fmt->fwidth--) {
                        wrchar(outbuf, fmt->fchar);
                        count++;
                }
@@ -135,12 +150,92 @@ static int wrstr(struct outbuf *outbuf, struct format *fmt, const char *s)
        return count;
 }
 
+static const char hexconv[] = "0123456789abcdef";
+
 static int wrint(struct outbuf *outbuf, struct format *fmt, long val)
 {
-       return 0;       /* TODO */
+       char buf[16], *ptr = buf + 15;
+       int neg = 0;
+
+       buf[15] = 0;
+
+       if(val < 0) {
+               neg = 1;
+               val = -val;
+       }
+
+       if(val == 0) {
+               *ptr++ = '0';
+       }
+
+       switch(fmt->base) {
+       case 16:
+               while(val) {
+                       *--ptr = hexconv[val & 0xf];
+                       val >>= 4;
+               }
+               break;
+
+       case 8:
+               while(val) {
+                       *--ptr = '0' | (val & 7);
+                       val >>= 3;
+               }
+               break;
+
+       default:        /* assume 10 */
+               /*
+               while(val) {
+                       *--ptr = '0' | (val % 10);
+                       val /= 10;
+               }
+               */
+               break;
+       }
+
+       if(neg) {
+               *--ptr = '-';
+       }
+       fmt->flags |= FMT_RALIGN;
+       return wrstr(outbuf, fmt, ptr);
 }
 
 static int wruint(struct outbuf *outbuf, struct format *fmt, unsigned long val)
 {
-       return 0;       /* TODO */
+       static const char hexconv[] = "0123456789abcdef";
+       char buf[16], *ptr = buf + 15;
+
+       buf[15] = 0;
+
+       if(val == 0) {
+               *ptr++ = '0';
+       }
+
+       switch(fmt->base) {
+       case 16:
+               while(val) {
+                       *--ptr = hexconv[val & 0xf];
+                       val >>= 4;
+               }
+               break;
+
+       case 8:
+               while(val) {
+                       *--ptr = '0' | (val & 7);
+                       val >>= 3;
+               }
+               break;
+
+       default:        /* assume 10 */
+               /*
+               while(val) {
+                       *--ptr = '0' | (val % 10);
+                       val /= 10;
+               }
+               */
+               break;
+       }
+
+       fmt->flags |= FMT_RALIGN;
+       return wrstr(outbuf, fmt, ptr);
 }
index 075715c..12388c5 100644 (file)
@@ -1,10 +1,12 @@
 #ifndef STDIO_H_
 #define STDIO_H_
 
+#include <stdarg.h>
 #include "con.h"
 
 #define putchar(c)     con_putchar(c)
 
 int printf(const char *fmt, ...);
+int vprintf(const char *fmt, va_list ap);
 
 #endif /* STDIO_H_ */
diff --git a/kern/src/libc/stdlib.c b/kern/src/libc/stdlib.c
new file mode 100644 (file)
index 0000000..b0ae8fb
--- /dev/null
@@ -0,0 +1,69 @@
+#include <stdlib.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 = (int)*str & 0xf;
+               } 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;
+}
+
diff --git a/kern/src/libc/stdlib.h b/kern/src/libc/stdlib.h
new file mode 100644 (file)
index 0000000..f8ff71b
--- /dev/null
@@ -0,0 +1,10 @@
+#ifndef STDLIB_H_
+#define STDLIB_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);
+
+#endif /* STDLIB_H_ */
index b59e371..9022900 100644 (file)
@@ -13,6 +13,7 @@ void kmain(void)
        con_init();
 
        printf("eightysix kernel %s\n", VERSTR);
+       printf("foo: %04x\n", 0xabc);
 
        init_intr();
 }