wm: teppich

Download patch

ref: bf6d794b8e8eb4bebd0bc8e692d5dec6265d285c
parent: bde44feca3fd7d9bf18732e478e379c39705efdd
author: mkf <mkf@cloud9p.org>
date: Thu Nov 9 11:19:51 EST 2023

import sources², add serial console

--- /dev/null
+++ b/include/com.h
@@ -1,0 +1,8 @@
+#pragma once
+#include <u.h>
+
+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
--- /dev/null
+++ b/include/libc.h
@@ -1,0 +1,4 @@
+#pragma once
+
+int strlen(char *s);
+int strcmp(char *s1, char *s2);
--- /dev/null
+++ b/include/pc.h
@@ -1,0 +1,2 @@
+#define COM1 0x3f8
+#define KB 0x60
--- /dev/null
+++ b/include/ps2.h
@@ -1,0 +1,121 @@
+#pragma once
+#define KB 0x60
+
+enum KB_CMD
+{
+	SET_LED = 0xED,
+	ECHO = 0xEE, /* no knock-knock jokes are allowed in this comment*/
+	SET_SCANCODE = 0xF0, 
+	IDENTIFY_KB = 0xF2, /* checks if something is there */
+	SET_RATE = 0xF3, /* also sets delay */
+
+	DO_SCAN = 0xF4,
+	DONT_SCAN = 0xF5, /* may also restore default parameters */
+
+	C_RESEND = 0xFE,
+	RESET = 0xFF,
+};
+
+enum KB_ANS
+{
+	INT_ERR1 = 0x00,
+	INT_ERR2 = 0xFF,
+
+	TEST_OK = 0xAA,
+	ECHO_ACK = 0xEE, 
+	CMD_ACK = 0xFA,
+	A_RESEND = 0xFE,
+
+	TEST_ERR1 = 0xFC, /* either of which may happen */
+	TEST_ERR2 = 0xFD,
+};
+
+/* 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? */
+};
--- /dev/null
+++ b/include/u.h
@@ -1,0 +1,14 @@
+#pragma once
+
+#define nil ((void*)0x0)
+
+typedef int size_t;
+
+typedef unsigned char uint8; 
+typedef char int8;
+
+typedef unsigned short uint16;
+typedef short int16;
+
+typedef unsigned long uint32;
+typedef long int32;
\ No newline at end of file
--- /dev/null
+++ b/include/vga.h
@@ -1,0 +1,38 @@
+#pragma once
+#include <u.h>
+
+static const size_t VGA_WIDTH = 80; /* x */
+static const size_t VGA_HEIGHT = 25; /* y */
+
+size_t vga_row;
+size_t vga_col;
+
+uint8 vga_color;
+uint16* vga_buf;
+
+enum {
+	BLACK = 0,
+	BLUE,
+	GREEN,
+	CYAN,
+	RED,
+	MAGENTA,
+	BROWN,
+	LIGHT_GREY,
+	DARK_GREY,
+	LIGHT_BLUE,
+	LIGHT_GREEN,
+	LIGHT_CYAN,
+	LIGHT_RED,
+	LIGHT_MAGENTA,
+	LIGHT_BROWN,
+	WHITE,
+};
+
+static uint8 vga_gencolor(int fg, int bg);
+static uint16 vga_char(unsigned char c, uint8 color);
+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
--- /dev/null
+++ b/include/x86.h
@@ -1,0 +1,18 @@
+#pragma once
+#include <u.h>
+
+#define COM1 0x3f8
+#define KB 0x60
+
+#define outb(port,data) asm volatile("out %0, %1" : : "a" (data), "d" (port));
+
+#define inb(port) ({ \
+unsigned char _v; \
+__asm__ volatile ("inb %%dx,%%al":"=a" (_v):"d" (port)); \
+_v; \
+})
+
+void instr(uint16 port, uint8* address, uint32 size);
+void sti(void);
+void cli(void);
+void nop(void);
--- /dev/null
+++ b/libc/strcmp.c
@@ -1,0 +1,17 @@
+int
+strcmp(char *s1, char *s2)
+{
+	unsigned int c1, c2;
+
+	for(;;) {
+		c1 = *s1++;
+		c2 = *s2++;
+		if(c1 != c2) {
+			if(c1 > c2)
+				return 1;
+			return -1;
+		}
+		if(c1 == 0)
+			return 0;
+	}
+}
--- /dev/null
+++ b/libc/strlen.c
@@ -1,0 +1,8 @@
+int
+strlen(char *s)
+{
+	int i = 0;
+	while(s[i])
+		i++;
+	return i;
+}
\ No newline at end of file
--- /dev/null
+++ b/pc/boot.s
@@ -1,0 +1,109 @@
+/* Declare constants for the multiboot header. */
+.set ALIGN,    1<<0             /* align loaded modules on page boundaries */
+.set MEMINFO,  1<<1             /* provide memory map */
+.set FLAGS,    ALIGN | MEMINFO  /* this is the Multiboot 'flag' field */
+.set MAGIC,    0x1BADB002       /* 'magic number' lets bootloader find the header */
+.set CHECKSUM, -(MAGIC + FLAGS) /* checksum of above, to prove we are multiboot */
+
+/* 
+Declare a multiboot header that marks the program as a kernel. These are magic
+values that are documented in the multiboot standard. The bootloader will
+search for this signature in the first 8 KiB of the kernel file, aligned at a
+32-bit boundary. The signature is in its own section so the header can be
+forced to be within the first 8 KiB of the kernel file.
+*/
+.section .multiboot
+.align 4
+.long MAGIC
+.long FLAGS
+.long CHECKSUM
+
+/*
+The multiboot standard does not define the value of the stack pointer register
+(esp) and it is up to the kernel to provide a stack. This allocates room for a
+small stack by creating a symbol at the bottom of it, then allocating 16384
+bytes for it, and finally creating a symbol at the top. The stack grows
+downwards on x86. The stack is in its own section so it can be marked nobits,
+which means the kernel file is smaller because it does not contain an
+uninitialized stack. The stack on x86 must be 16-byte aligned according to the
+System V ABI standard and de-facto extensions. The compiler will assume the
+stack is properly aligned and failure to align the stack will result in
+undefined behavior.
+*/
+.section .bss
+.align 16
+stack_bottom:
+.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.
+	*/
+	mov $stack_top, %esp
+
+	/*
+	This is a good place to initialize crucial processor state before the
+	high-level kernel is entered. It's best to minimize the early
+	environment where crucial features are offline. Note that the
+	processor is not fully initialized yet: Features such as floating
+	point instructions and instruction set extensions are not initialized
+	yet. The GDT should be loaded here. Paging should be enabled here.
+	C++ features such as global constructors and exceptions will require
+	runtime support to work as well.
+	*/
+
+	/*
+	Enter the high-level kernel. The ABI requires the stack is 16-byte
+	aligned at the time of the call instruction (which afterwards pushes
+	the return pointer of size 4 bytes). The stack was originally 16-byte
+	aligned above and we've pushed a multiple of 16 bytes to the
+	stack since (pushed 0 bytes so far), so the alignment has thus been
+	preserved and the call is well defined.
+	*/
+	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