wm: teppich

Download patch

ref: 086331e6bf7b682b12ca392130160a1afb371f12
parent: c2d48b328d4c3d0b91d657e89e2da3a97cd1b528
author: mkf <mkf@cloud9p.org>
date: Mon Nov 13 01:59:06 EST 2023

God knows what i did.

add a half-baked ps2 thingi, add backspace support to console-vga, simplify boot.s, a simple shell like, some fixes on com.h as well.

--- a/Makefile
+++ b/Makefile
@@ -14,6 +14,8 @@
 L=\
 	libc/strlen.o\
 	libc/strcmp.o\
+	libc/memcpy.o\
+	libc/memset.o\
 
 K=\
 	pc/x86.o\
@@ -20,6 +22,7 @@
 	pc/kern.o\
 	pc/boot.o\
 	pc/vga.o\
+	pc/ps2.o\
 	pc/com.o\
 	${L}
 
@@ -37,4 +40,4 @@
 	rm -f *.o *.elf ${K}
 
 qemu: teppich.elf
-	$(QEMU) $(QFLAGS) teppich.elf
\ No newline at end of file
+	$(QEMU) $(QFLAGS) teppich.elf
--- a/include/com.h
+++ b/include/com.h
@@ -3,6 +3,8 @@
 
 void com_init(uint16 port, uint32 baud_rate);
 void com_putchar(uint16 port, uint8 c);
-uint8 com_getchar(uint16 port);
-void com1_putchar(char c);
-void com1_puts(char* s);
\ No newline at end of file
+void com_putc(char c);
+void com_puts(char* s);
+char com_getchar(uint16 port);
+char com_getc(void);
+char* com_getl(void);
\ No newline at end of file
--- a/include/libc.h
+++ b/include/libc.h
@@ -2,3 +2,5 @@
 
 int strlen(char *s);
 int strcmp(char *s1, char *s2);
+void* memset(void* src, char c, unsigned int len);
+void* memcpy(void *a1, void *a2, unsigned int len);
--- a/include/ps2.h
+++ b/include/ps2.h
@@ -1,6 +1,30 @@
 #pragma once
 #define KB 0x60
 
+static char keymap[128] = {
+	"\0\x1b""1234567890-=\b\t"
+	"qwertyuiop[]\r\0as"
+	"dfghjkl;'`\0\\zxcv"
+	"bnm,./\0*\0 \0\0\0\0\0\0"
+	"\0\0\0\0\0\0\0""789-456+1"
+	"230."
+};
+
+static char shifted_kbmap[128] =
+{
+	"\0\x1b""!@#$%^&*()_+\b\t"
+	"QWERTYUIOP{}\r\0AS"
+	"DFGHJKL:\"~\0|ZXCV"
+	"BNM<>?\0\0\0 \0\0\0\0\0\0"
+	"\0\0\0\0\0\0\0""789-456+1"
+	"230."
+};
+
+enum KB_CTR_CMD
+{
+	ENABLE = 0xAE,
+};
+
 enum KB_CMD
 {
 	SET_LED = 0xED,
@@ -31,91 +55,6 @@
 };
 
 /* minix's input.h, Bedankt anderw, heel gaaf!  */
-enum {
-	KEY_A = 0x0004,
-	KEY_B,
-	KEY_C,
-	KEY_D,
-	KEY_E,
-	KEY_F,
-	KEY_G,
-	KEY_H,
-	KEY_I,
-	KEY_J,
-	KEY_K,
-	KEY_L,
-	KEY_M,
-	KEY_N,
-	KEY_O,
-	KEY_P,
-	KEY_Q,
-	KEY_R,
-	KEY_S,
-	KEY_T,
-	KEY_U,
-	KEY_V,
-	KEY_W,
-	KEY_X,
-	KEY_Y,
-	KEY_Z,
-	KEY_1,
-	KEY_2,
-	KEY_3,
-	KEY_4,
-	KEY_5,
-	KEY_6,
-	KEY_7,
-	KEY_8,
-	KEY_9,
-	KEY_0,
 
-	KEY_ENTER,
-	KEY_ESCAPE,
-	KEY_BACKSPACE,
-	KEY_TAB,
-	KEY_SPACEBAR,
-	KEY_DASH,
-	KEY_EQUAL,
-	KEY_OPEN_BRACKET,
-	KEY_CLOSE_BRACKET,
-	KEY_BACKSLASH,
-	KEY_EUROPE_1,
-	KEY_SEMICOLON,
-	KEY_APOSTROPH,
-	KEY_GRAVE_ACCENT,
-	KEY_COMMA,
-	KEY_PERIOD,
-	KEY_SLASH,
-	KEY_CAPS_LOCK,
-
-	KEY_F1,
-	KEY_F2,
-	KEY_F3,
-	KEY_F4,
-	KEY_F5,
-	KEY_F6,
-	KEY_F7,
-	KEY_F8,
-	KEY_F9,
-	KEY_F10,
-	KEY_F11,
-	KEY_F12,
-
-	KEY_PRINT_SCREEN,
-	KEY_SCROLL_LOCK,
-	KEY_PAUSE,
-	KEY_INSERT,
-	KEY_HOME,
-	KEY_PAGE_UP,
-	KEY_DELETE,
-	KEY_END,
-	KEY_PAGE_DOWN,
-	KEY_RIGHT_ARROW,
-	KEY_LEFT_ARROW,
-	KEY_DOWN_ARROW,
-	KEY_UP_ARROW,
-	KEY_NUM_LOCK,
-
-	/* did you expected to see the reset of scan codes here?
-		who do you think i am? a nerd? */
-};
+char ps2_getc(void);
+void ps2_init(void);
--- a/include/vga.h
+++ b/include/vga.h
@@ -31,8 +31,9 @@
 
 static uint8 vga_gencolor(int fg, int bg);
 static uint16 vga_char(unsigned char c, uint8 color);
+void vga_clear(char c);
 void vga_init(int fg, int bg);
 void vga_writeto(char c, uint8 color, int x, int y);
 void vga_nl(void);
 void vga_putc(char c);
-void vga_puts(char *s);
\ No newline at end of file
+void vga_puts(char *s);
--- a/include/x86.h
+++ b/include/x86.h
@@ -1,8 +1,9 @@
 #pragma once
 #include <u.h>
 
-#define COM1 0x3f8
+#define COM1 0x3F8
 #define KB 0x60
+#define KB_CTR 0x64
 
 #define outb(port,data) asm volatile("out %0, %1" : : "a" (data), "d" (port));
 
--- a/pc/boot.s
+++ b/pc/boot.s
@@ -36,33 +36,10 @@
 .skip 16384 # 16 KiB
 stack_top:
 
-/*
-The linker script specifies _start as the entry point to the kernel and the
-bootloader will jump to this position once the kernel has been loaded. It
-doesn't make sense to return from this function as the bootloader is gone.
-*/
 .section .text
 .global _start
-.type _start, @function
 _start:
-	/*
-	The bootloader has loaded us into 32-bit protected mode on a x86
-	machine. Interrupts are disabled. Paging is disabled. The processor
-	state is as defined in the multiboot standard. The kernel has full
-	control of the CPU. The kernel can only make use of hardware features
-	and any code it provides as part of itself. There's no printf
-	function, unless the kernel provides its own <stdio.h> header and a
-	printf implementation. There are no security restrictions, no
-	safeguards, no debugging mechanisms, only what the kernel provides
-	itself. It has absolute and complete power over the
-	machine.
-	*/
-
-	/*
-	To set up a stack, we set the esp register to point to the top of the
-	stack (as it grows downwards on x86 systems). This is necessarily done
-	in assembly as languages such as C cannot function without a stack.
-	*/
+	/* c needs a stack */
 	mov $stack_top, %esp
 
 	/*
@@ -86,24 +63,3 @@
 	*/
 	call kernel_main
 
-	/*
-	If the system has nothing more to do, put the computer into an
-	infinite loop. To do that:
-	1) Disable interrupts with cli (clear interrupt enable in eflags).
-	   They are already disabled by the bootloader, so this is not needed.
-	   Mind that you might later enable interrupts and return from
-	   kernel_main (which is sort of nonsensical to do).
-	2) Wait for the next interrupt to arrive with hlt (halt instruction).
-	   Since they are disabled, this will lock up the computer.
-	3) Jump to the hlt instruction if it ever wakes up due to a
-	   non-maskable interrupt occurring or due to system management mode.
-	*/
-	cli
-1:	hlt
-	jmp 1b
-
-/*
-Set the size of the _start symbol to the current location '.' minus its start.
-This is useful when debugging or when you implement call tracing.
-*/
-.size _start, . - _start
--- a/pc/com.c
+++ b/pc/com.c
@@ -52,7 +52,20 @@
 	outb(port, c);
 }
 
-uint8
+void
+com_putc(char c)
+{
+	com_putchar(COM1, c);
+}
+
+void
+com_puts(char* s)
+{
+	for(int i = 0 ; i < strlen(s) ; i++)
+		com_putc(s[i]);
+}
+
+char
 com_getchar(uint16 port)
 {
 	while(!(inb(port + 5) & 1))
@@ -60,15 +73,21 @@
 	return inb(port);
 }
 
-void
-com1_putchar(char c)
+char
+com_getc(void)
 {
-	com_putchar(COM1, c);
+	return com_getchar(COM1);
 }
 
-void
-com1_puts(char* s)
+char*
+com_getl(void)
 {
-	for(int i = 0 ; i < strlen(s) ; i++)
-		com1_putchar(s[i]);
+	char *cmd, c;
+	int i = 0;
+	/* might c be '\n'? unlikely */
+	while(c != '\n')
+	{
+		cmd[i] = c;
+	}
+	return cmd;
 }
\ No newline at end of file
--- a/pc/kern.c
+++ b/pc/kern.c
@@ -1,17 +1,84 @@
 #include <vga.h>
 #include <com.h>
 #include <ps2.h>
+#include <libc.h>
 
 /* abandon hope, all ye who enter here */
-void panic(void)
+void
+panic(void)
 {
 	vga_puts("panic: give up. it's over.\n");
-	com1_puts("panic: give up. it's over.\n");
+	com_puts("panic: give up. it's over.\n");
+	
 }
 
-void kernel_main(void) 
+int
+run(char* cmd)
 {
+	/* vga_puts(cmd); */
+
+	/* replace it with a proper table */
+	if(!strcmp(cmd, "clear"))
+	{
+		vga_clear(' ');
+	}
+	else if(!strcmp(cmd, "hello"))
+	{
+		vga_puts("hi");
+	}
+	else if(!strcmp(cmd, "reboot"))
+		return 0;
+	else
+		vga_puts("no such command");
+
+	vga_putc('\n');
+	return 1;
+
+}
+
+void
+repl(void)
+{
+	char c;
+	char *cmd = "";
+	int i = 0;
+
+	vga_puts("salam az Teppich\n");
+	vga_puts("> ");
+
+	while(1)
+	{
+
+		c = ps2_getc();
+		if(c == 0)
+			continue;
+
+		vga_putc(c);
+
+		if(c == '\r' || c == '\n')
+		{
+			if(!run(cmd))
+				return;
+			/* clear the mess */
+			i = 0;
+			memset(cmd, 0, 16);
+
+			vga_puts("> ");
+
+		}
+		else
+		{
+			*(cmd+i) = c; /* heb */
+			i++;
+		}
+	}
+}
+
+
+void
+kernel_main(void) 
+{
 	vga_init(WHITE, BLUE);
-	vga_puts("check out serial console");
-	com1_puts("check out VGA console");
+
+	repl();
 }
--- a/pc/ps2.c
+++ b/pc/ps2.c
@@ -1,0 +1,34 @@
+#include <u.h>
+#include <x86.h>
+#include <ps2.h>
+
+uint8
+ps2_read_status(void)
+{
+	return inb(KB_CTR);
+}
+
+void
+ps2_init()
+{
+	int a = 256 - 3; // 2^8 - 1- 2
+	outb(0x64, SET_RATE);
+	outb(0x64, a);
+}
+
+char
+ps2_getc()
+{
+	char c;
+	while(1)
+	{
+		if(!(ps2_read_status() & 1))
+			return 0;
+
+		c = inb(KB);
+		if(c & 0x80)
+			return 0;
+		return keymap[c];
+
+	}
+}
--- a/pc/vga.c
+++ b/pc/vga.c
@@ -21,10 +21,12 @@
 	{
 		for (size_t x = 0; x < VGA_WIDTH; x++)
 		{
-			const size_t index = y * VGA_WIDTH + x;
+			uint16 index = y * VGA_WIDTH + x;
 			vga_buf[index] = vga_char(c, vga_color);
 		}
 	}
+	vga_row = 0;
+	vga_col = 0;
 }
 
 void
@@ -57,8 +59,10 @@
 void
 vga_putc(char c)
 {
+	int index = vga_row * VGA_WIDTH + vga_col;
 	switch(c)
 	{
+		case '\r':
 		case '\n':
 			vga_nl();
 			return;
@@ -65,6 +69,33 @@
 		case '\t':
 			for(int i = 0 ; i < 4 ; i++)
 				vga_putc(' ');
+			return;
+		case '\b':
+			if(vga_col > 0)
+			{
+				/* index points at current loction of cursor, which is empty. */
+				vga_buf[index - 1] = vga_char(' ', vga_color);
+				vga_col--;
+			}
+
+			/*
+			is the following needed? i wonder.
+			i'm aware of no OSes that allow their raw terminal interface
+			allow returing to previous lines.
+			only Plan 9 console driver allows this on rio.
+
+			maybe it's safer to skip it.... for now.
+
+			else if(vga_row == 0)
+			{
+			// we need a smarter terminal-ish version
+			//		smh like
+			//		vga_row = vga_find_last_nonchar(' ');
+
+				vga_row = VGA_WIDTH;
+			}
+			*/
+
 			return;
 		default:
 			vga_writeto(c, vga_color, vga_col, vga_row);