aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoraqua <aqua@iserlohn-fortress.net>2022-11-08 17:19:45 +0200
committeraqua <aqua@iserlohn-fortress.net>2022-11-08 17:54:13 +0200
commitdbdaa77fb5924b4b9e6b374a44ef76481a38d3d2 (patch)
treeabd4daf428532ac026a538e20138907b36c795c3
parentAdd python-sphinx docs (diff)
downloadkernel-dbdaa77fb5924b4b9e6b374a44ef76481a38d3d2.tar.xz
Add FILE struct
-rw-r--r--devices/uart_16550.c78
-rw-r--r--devices/uart_16550.h8
-rw-r--r--devices/vga.c78
-rw-r--r--devices/vga.h8
-rw-r--r--doc.src/devices.rst2
-rw-r--r--doc.src/libk.rst3
-rw-r--r--lib/Makefile2
-rw-r--r--lib/stdio.h34
-rw-r--r--lib/stdio/fprintf.c11
-rw-r--r--lib/stdio/printf.c69
-rw-r--r--lib/stdio/vfprintf.c54
-rw-r--r--lib/stdlib.h4
-rw-r--r--src/kernel.c13
13 files changed, 223 insertions, 141 deletions
diff --git a/devices/uart_16550.c b/devices/uart_16550.c
index 22f33ad..40ac594 100644
--- a/devices/uart_16550.c
+++ b/devices/uart_16550.c
@@ -1,4 +1,5 @@
#include "uart_16550.h"
+#include <stddef.h>
#include <sys/io.h>
enum uart_16550_offset {
@@ -43,67 +44,74 @@ enum LineStatus {
};
int
-uart_init(enum UART port)
-{
- outb(0x00, port + 1); // Disable all interrupts
- outb(0x80, port + 3); // Enable DLAB (set baud rate divisor)
- outb(0x03, port + 0); // Set divisor to 3 (lo byte) 38400 baud
- outb(0x00, port + 1); // (hi byte)
- outb(0x03, port + 3); // 8 bits, no parity, one stop bit
- outb(0xc7, port + 2); // Enable FIFO, clear them, with 14-byte threshold
- outb(0x0b, port + 4); // IRQs enabled, RTS/DSR set
- outb(0x1e, port + 4); // Set in loopback mode, test the serial chip
- outb(0xae, port + 0); // Test serial chip (send byte 0xAE and check if serial
- // returns same byte)
-
- // Check if serial is faulty (i.e: not same byte as sent)
- if (inb(port + 0) != 0xae) {
- return 1;
- }
-
- // If serial is not faulty set it in normal operation mode
- // (not-loopback with IRQs enabled and OUT#1 and OUT#2 bits enabled)
- outb(0x0f, port + 4);
- return 0;
-}
-
-int
uart_thre(enum UART port)
{
return inb(port + LineStatus) & THRE;
}
void
-uart_write(enum UART port, char a)
+uart_write(const FILE *self, char a)
{
- while (uart_thre(port) == 0)
- ;
- outb(a, port);
+ while (uart_thre(self->id) == 0) {}
+ outb(a, self->id);
if (a == '\n') {
- while (uart_thre(port) == 0)
- ;
- outb('\r', port);
+ while (uart_thre(self->id) == 0) {}
+ outb('\r', self->id);
}
}
int
-uart_puts(enum UART port, const char *string, int length)
+uart_puts(const FILE *self, const char *string, int length)
{
int written = 0;
if (length == -1)
while (*string != '\0') {
- uart_write(port, *string);
+ uart_write(self, *string);
++string;
++written;
}
else
for (int i = 0; i < length; ++i) {
- uart_write(port, string[i]);
+ uart_write(self, string[i]);
++written;
}
return written;
}
+
+void
+uart_flush(const FILE *self)
+{
+}
+
+FILE uart_stream;
+
+FILE *
+uart_init(enum UART port)
+{
+ outb(0x00, port + 1); // Disable all interrupts
+ outb(0x80, port + 3); // Enable DLAB (set baud rate divisor)
+ outb(0x03, port + 0); // Set divisor to 3 (lo byte) 38400 baud
+ outb(0x00, port + 1); // (hi byte)
+ outb(0x03, port + 3); // 8 bits, no parity, one stop bit
+ outb(0xc7, port + 2); // Enable FIFO, clear them, with 14-byte threshold
+ outb(0x0b, port + 4); // IRQs enabled, RTS/DSR set
+ outb(0x1e, port + 4); // Set in loopback mode, test the serial chip
+ outb(0xae, port + 0); // Test serial chip (send byte 0xAE and check if serial
+ // returns same byte)
+
+ // Check if serial is faulty (i.e: not same byte as sent)
+ if (inb(port + 0) != 0xae) { return NULL; }
+
+ // If serial is not faulty set it in normal operation mode
+ // (not-loopback with IRQs enabled and OUT#1 and OUT#2 bits enabled)
+ outb(0x0f, port + 4);
+ uart_stream.id = port;
+ uart_stream.putc = &uart_write;
+ uart_stream.puts = &uart_puts;
+ uart_stream.flush = &uart_flush;
+ return &uart_stream;
+}
diff --git a/devices/uart_16550.h b/devices/uart_16550.h
index bb219cc..5e5ee13 100644
--- a/devices/uart_16550.h
+++ b/devices/uart_16550.h
@@ -1,5 +1,7 @@
#pragma once
+#include <stdio.h>
+
enum UART {
COM1 = 0x3f8,
COM2 = 0x2f8,
@@ -11,6 +13,6 @@ enum UART {
COM8 = 0x4E8,
};
-int uart_init(enum UART port);
-void uart_write(enum UART port, char a);
-int uart_puts(enum UART port, const char *string, int length);
+FILE *uart_init(enum UART port);
+// void uart_write(enum UART port, char a);
+// int uart_puts(enum UART port, const char *string, int length);
diff --git a/devices/vga.c b/devices/vga.c
index 39370ba..12ac880 100644
--- a/devices/vga.c
+++ b/devices/vga.c
@@ -55,31 +55,9 @@ vga_update_cursor()
outb((pos >> 8) & 0xff, cga_dat_port);
}
-// *** Text Mode ***
-void
-vga_init()
-{
- buffer = (struct VGAEntry *)0xc03ff000;
- vga_enable_cursor(14, 15);
- vga_clear(VGA_COLOR_LIGHT_BLUE, VGA_COLOR_LIGHT_GREY);
-}
-
-void
-vga_clear(enum vga_color foreground, enum vga_color background)
-{
- for (int y = 0; y < height; ++y)
- for (int x = 0; x < width; ++x) {
- const int index = y * width + x;
- buffer[index].text = ' ';
- buffer[index].foreground = foreground;
- buffer[index].background = background;
- }
- col = row = 0;
- vga_update_cursor();
-}
-
+// *** Text Mode Output ***
void
-vga_putc(char a)
+vga_putc(const FILE *self, char a)
{
switch (a) {
case '\n':
@@ -117,16 +95,58 @@ vga_putc(char a)
}
}
-void
-vga_puts(const char *string, int len)
+int
+vga_puts(const FILE *self, const char *string, int len)
{
-
+ int written = 0;
if (len == -1)
while (*string != '\0') {
- vga_putc(*string);
+ vga_putc(self, *string);
++string;
+ ++written;
}
else
- for (int i = 0; i < len; ++i) { vga_putc(string[i]); }
+ for (int i = 0; i < len; ++i) {
+ vga_putc(self, string[i]);
+ ++written;
+ }
+ return written;
+}
+
+void
+vga_flush(const FILE *self)
+{
+ vga_update_cursor();
+}
+
+// *** Text Mode ***
+FILE vga_stream;
+
+FILE *
+vga_init()
+{
+ buffer = (struct VGAEntry *)0xc03ff000;
+ vga_enable_cursor(14, 15);
+ vga_clear(VGA_COLOR_LIGHT_BLUE, VGA_COLOR_LIGHT_GREY);
+
+ vga_stream.id = 0;
+ vga_stream.putc = &vga_putc;
+ vga_stream.puts = &vga_puts;
+ vga_stream.flush = &vga_flush;
+ return &vga_stream;
+}
+
+void
+vga_clear(enum vga_color foreground, enum vga_color background)
+{
+ for (int y = 0; y < height; ++y)
+ for (int x = 0; x < width; ++x) {
+ const int index = y * width + x;
+ buffer[index].text = ' ';
+ buffer[index].foreground = foreground;
+ buffer[index].background = background;
+ }
+ col = row = 0;
+ vga_update_cursor();
}
diff --git a/devices/vga.h b/devices/vga.h
index daaa482..d9dfd44 100644
--- a/devices/vga.h
+++ b/devices/vga.h
@@ -1,5 +1,7 @@
#pragma once
+#include <stdio.h>
+
/** Hardware text mode color constants. */
enum vga_color {
VGA_COLOR_BLACK = 0,
@@ -20,11 +22,11 @@ enum vga_color {
VGA_COLOR_WHITE = 15,
};
-void vga_init();
+FILE *vga_init();
void vga_clear(enum vga_color foreground, enum vga_color background);
-void vga_putc(char a);
-void vga_puts(const char *string, int len);
+// void vga_putc(char a);
+// void vga_puts(const char *string, int len);
// void vga_enable_cursor(unsigned char start, unsigned char end);
// void vga_disable_cursor();
diff --git a/doc.src/devices.rst b/doc.src/devices.rst
index 7c8b41d..13bc2f0 100644
--- a/doc.src/devices.rst
+++ b/doc.src/devices.rst
@@ -10,6 +10,7 @@ Text mode
osdev wiki: `Text UI <https://wiki.osdev.org/Text_mode>`_
.. c:autodoc:: ../devices/vga.h
+ :clang: -isystem/usr/lib/gcc/i686-elf/12.2.0/include
PS/2 Controller
===============
@@ -30,4 +31,5 @@ Programmable Interrupt Controller
UART
====
.. c:autodoc:: ../devices/uart_16550.h
+ :clang: -isystem/usr/lib/gcc/i686-elf/12.2.0/include
diff --git a/doc.src/libk.rst b/doc.src/libk.rst
index 7c30f41..078198c 100644
--- a/doc.src/libk.rst
+++ b/doc.src/libk.rst
@@ -7,11 +7,14 @@ libk is the kernel's C standard library implementation.
stdio.h
=======
.. c:autodoc:: ../lib/stdio.h
+ :clang: -isystem/usr/lib/gcc/i686-elf/12.2.0/include
stdlib.h
========
.. c:autodoc:: ../lib/stdlib.h
+ :clang: -isystem/usr/lib/gcc/i686-elf/12.2.0/include
string.h
========
.. c:autodoc:: ../lib/string.h
+ :clang: -isystem/usr/lib/gcc/i686-elf/12.2.0/include
diff --git a/lib/Makefile b/lib/Makefile
index 66181c8..f564ee0 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -2,7 +2,7 @@ include ../Makefile.config
CCFLAGS += -I. -I..
-libk.SRCS = stdio/printf.c \
+libk.SRCS = stdio/printf.c stdio/fprintf.c stdio/vfprintf.c \
stdlib/memcpy.c stdlib/memset.c \
string/itoa.c
diff --git a/lib/stdio.h b/lib/stdio.h
index 201cce1..4711a29 100644
--- a/lib/stdio.h
+++ b/lib/stdio.h
@@ -1,6 +1,38 @@
#pragma once
+#include <stdarg.h>
+
+/** An object type used for streams */
+typedef struct FILE_t {
+ int id;
+ /** Functions that prints a character to the stream */
+ void (*putc)(const struct FILE_t *, char);
+ /** Function that prints a string to the stream */
+ int (*puts)(const struct FILE_t *, const char *, int);
+ /** Flush all buffers */
+ void (*flush)(const struct FILE_t *);
+} FILE;
+
+/** A FILE value corresponding to stdin, the keyboard buffer */
+extern FILE *stdin;
+/** A FILE value corresponding to stdout, the display */
+extern FILE *stdout;
+/** A FILE value corresponding to stderr, the uart */
+extern FILE *stderr;
+
/**
- * Supports %s (string), %d (decimal), %u (unsigned), %x (hexadecimal)
+ * Write the formatted string to stdout
+ *
+ * Supports ``%s`` (string), ``%d`` (decimal), ``%u`` (unsigned), ``%x`` (hexadecimal)
*/
int printf(const char *restrict format, ...);
+
+/**
+ * Write the formatted string to stream; see printf
+ */
+int fprintf(FILE *restrict stream, const char *restrict format, ...);
+
+/**
+ * Write the formatted string to stream; see printf
+ */
+int vfprintf(FILE *restrict stream, const char *restrict format, va_list ap);
diff --git a/lib/stdio/fprintf.c b/lib/stdio/fprintf.c
new file mode 100644
index 0000000..9a96dc6
--- /dev/null
+++ b/lib/stdio/fprintf.c
@@ -0,0 +1,11 @@
+#include <stdio.h>
+
+int
+fprintf(FILE *restrict stream, const char *restrict format, ...)
+{
+ va_list ap;
+ va_start(ap, format);
+ int c = vfprintf(stream, format, ap);
+ va_end(ap);
+ return c;
+}
diff --git a/lib/stdio/printf.c b/lib/stdio/printf.c
index ae4d5b1..4efc1ac 100644
--- a/lib/stdio/printf.c
+++ b/lib/stdio/printf.c
@@ -1,70 +1,11 @@
-#include <stdarg.h>
#include <stdio.h>
-#include <string.h>
-
-#include <devices/uart_16550.h>
-#include <devices/vga.h>
-
-static char buffer[3 * sizeof(int) + 2];
int
printf(const char *restrict format, ...)
{
- int written = 0;
- va_list params;
- va_start(params, format);
-
- int s = 0;
- int l = 0;
- for (int i = 0; format[i] != '\0'; ++i) {
- if (format[i] == '%') {
- written += uart_puts(COM1, &format[s], l);
- vga_puts(&format[s], l);
- s = i + 2;
- ++i;
-
- switch (format[i]) {
- case 's': {
- const char *arg = va_arg(params, const char *);
- written += uart_puts(COM1, arg, -1);
- vga_puts(arg, -1);
- } break;
- case 'c': {
- const int arg = va_arg(params, int);
- uart_write(COM1, arg);
- vga_putc(arg);
- ++written;
- } break;
- case 'd': {
- const char *arg = itoa(buffer, va_arg(params, int), 10);
- written += uart_puts(COM1, arg, -1);
- vga_puts(arg, -1);
- } break;
- case 'u': {
- const char *arg = utoa(buffer, va_arg(params, unsigned int), 10);
- written += uart_puts(COM1, arg, -1);
- vga_puts(arg, -1);
- } break;
- case 'x': {
- const char *arg = utoa(buffer, va_arg(params, unsigned int), 16);
- written += uart_puts(COM1, arg, -1);
- vga_puts(arg, -1);
- } break;
- }
-
- l = 0;
- }
-
- else
- ++l;
- }
-
- if (l > 0) {
- written += uart_puts(COM1, &format[s], l);
- vga_puts(&format[s], l);
- }
-
- va_end(params);
- vga_update_cursor();
- return written;
+ va_list ap;
+ va_start(ap, format);
+ int c = vfprintf(stdout, format, ap);
+ va_end(ap);
+ return c;
}
diff --git a/lib/stdio/vfprintf.c b/lib/stdio/vfprintf.c
new file mode 100644
index 0000000..d24e43e
--- /dev/null
+++ b/lib/stdio/vfprintf.c
@@ -0,0 +1,54 @@
+#include <stdio.h>
+#include <string.h>
+
+static char buffer[3 * sizeof(int) + 2];
+
+int
+vfprintf(FILE *restrict stream, const char *restrict format, va_list params)
+{
+ int written = 0;
+
+ int s = 0;
+ int l = 0;
+ for (int i = 0; format[i] != '\0'; ++i) {
+ if (format[i] == '%') {
+ written += stream->puts(stream, &format[s], l);
+ s = i + 2;
+ ++i;
+
+ switch (format[i]) {
+ case 's': {
+ const char *arg = va_arg(params, const char *);
+ written += stream->puts(stream, arg, -1);
+ } break;
+ case 'c': {
+ const int arg = va_arg(params, int);
+ stream->putc(stream, arg);
+ ++written;
+ } break;
+ case 'd': {
+ const char *arg = itoa(buffer, va_arg(params, int), 10);
+ written += stream->puts(stream, arg, -1);
+ } break;
+ case 'u': {
+ const char *arg = utoa(buffer, va_arg(params, unsigned int), 10);
+ written += stream->puts(stream, arg, -1);
+ } break;
+ case 'x': {
+ const char *arg = utoa(buffer, va_arg(params, unsigned int), 16);
+ written += stream->puts(stream, arg, -1);
+ } break;
+ }
+
+ l = 0;
+ }
+
+ else
+ ++l;
+ }
+
+ if (l > 0) { written += stream->puts(stream, &format[s], l); }
+
+ stream->flush(stream);
+ return written;
+}
diff --git a/lib/stdlib.h b/lib/stdlib.h
index 7f235f0..bd8474d 100644
--- a/lib/stdlib.h
+++ b/lib/stdlib.h
@@ -1,9 +1,11 @@
#pragma once
+#include <stddef.h>
+
/**
* Allocate size bytes and return a pointer to the allocated memory
*/
-void *malloc(unsigned int size);
+void *malloc(size_t size);
/**
* Free the memory space pointed to by ptr
diff --git a/src/kernel.c b/src/kernel.c
index 2777f72..a315f3b 100644
--- a/src/kernel.c
+++ b/src/kernel.c
@@ -15,11 +15,16 @@
#include <stdio.h>
#include <sys/cpuid.h>
+FILE *stdin;
+FILE *stdout;
+FILE *stderr;
+
void kmain() {
- vga_init(vmm_map(0xb8000, 0xc03ff000));
- if (uart_init(COM1) != 0) printf("UART self-test failed.\r\n");
+ stderr = uart_init(COM1);
+ stdout = vga_init(vmm_map(0xb8000, 0xc03ff000));
printf("glitch [version " VERSION "] [" CC "]\n");
+ fprintf(stderr, "glitch [version " VERSION "] [" CC "]\n");
{
char vendor[13] = {'\0'};
unsigned int eax;
@@ -27,6 +32,7 @@ void kmain() {
struct CPUVersion v;
__get_cpuid(1, (unsigned int *)&v, &eax, &eax, &eax);
printf("CPU: %s family %u model %u stepping %u\n", vendor, family(v), model(v), v.stepping);
+ fprintf(stderr, "CPU: %s family %u model %u stepping %u\n", vendor, family(v), model(v), v.stepping);
}
pic_init();
@@ -46,6 +52,5 @@ void kmain() {
// asm volatile("int $0x80");
- while (1)
- ;
+ while (1) {}
}