summaryrefslogtreecommitdiff
path: root/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'kernel')
-rw-r--r--kernel/SConscript2
-rw-r--r--kernel/main.c23
-rw-r--r--kernel/printf.c96
-rw-r--r--kernel/printf.h6
-rw-r--r--kernel/types.h2
5 files changed, 110 insertions, 19 deletions
diff --git a/kernel/SConscript b/kernel/SConscript
index 856d2b5..8c17467 100644
--- a/kernel/SConscript
+++ b/kernel/SConscript
@@ -27,4 +27,4 @@ kernel_bld = Builder(
env.Append(BUILDERS = {'Kernel' : kernel_bld})
-kernel = env.Kernel('kernel', ['kernel.ld', 'entry.c', 'main.c', 'gdt.c', 'idt.c'])
+kernel = env.Kernel('kernel', ['kernel.ld', 'entry.c', 'main.c', 'printf.c', 'gdt.c', 'idt.c'])
diff --git a/kernel/main.c b/kernel/main.c
index cc0dc35..55476ce 100644
--- a/kernel/main.c
+++ b/kernel/main.c
@@ -1,19 +1,17 @@
+#include "printf.h"
#include "gdt.h"
#include "idt.h"
-void kernel_serial_out(char* str);
-
void main() {
-
- kernel_serial_out("main()\n");
+ printf("main()\n");
gdt_init();
- kernel_serial_out("GDT set.\n");
+ printf("GDT set.\n");
idt_init();
- kernel_serial_out("IDT set.\n");
+ printf("IDT set.\n");
- kernel_serial_out("Halting.\n");
+ printf("Halting.\n");
asm volatile(
"cli\n"
@@ -21,14 +19,3 @@ void main() {
);
while(1);
}
-
-#define outb(port, value) asm volatile("out %b0,%w1" : : "a" (value), "d" (port));
-
-void kernel_serial_out(char* str) {
- while(*str) {
- if(*str == '\n') {
- outb(0x3f8, '\r');
- }
- outb(0x3f8, *str++);
- }
-}
diff --git a/kernel/printf.c b/kernel/printf.c
new file mode 100644
index 0000000..4b3a632
--- /dev/null
+++ b/kernel/printf.c
@@ -0,0 +1,96 @@
+#include "printf.h"
+#include "types.h"
+
+#define outb(port, value) asm volatile("out %b0,%w1" : : "a" (value), "d" (port));
+
+void putchar(char c) {
+ if(c == '\n') {
+ outb(0x3f8, '\r');
+ }
+ outb(0x3f8, c);
+}
+
+int printf(const char* format, ...) {
+ int32_t* argp = (int32_t*)&format;
+ int num;
+
+ while(*format) {
+ if(*format != '%') {
+ putchar(*format++);
+ num++;
+ continue;
+ }
+ format++;
+
+ bool is_signed = false;
+ bool zero_pad = false;
+ int radix = 16;
+ int min_len = 0;
+
+ if(*format == '0') {
+ zero_pad = true;
+ }
+
+ while(*format >= '0' && *format <= '9') {
+ min_len = min_len * 10 + *format++ - '0';
+ }
+
+ switch(*format++) {
+ case '%':
+ putchar('%');
+ num++;
+ break;
+
+ case 'c':
+ putchar((char)*++argp);
+ num++;
+ break;
+
+ case 's':
+ ;
+ char* str = (char*)*++argp;
+ while(*str) {
+ putchar(*str++);
+ num++;
+ }
+ break;
+
+ case 'd':
+ is_signed = true;
+ case 'u':
+ radix = 10;
+ case 'x':
+ ;
+ uint32_t x = (uint32_t)*(++argp);
+ if(is_signed && (int32_t)x < 0) {
+ x = -x;
+ putchar('-');
+ min_len--;
+ }
+
+ char buf[11];
+ char* bufp = &buf[sizeof(buf)];
+ *--bufp = 0;
+
+ do {
+ int d = x % radix;
+ *--bufp = d < 10 ? '0' + d : 'a' - 10 + d;
+ x /= radix;
+ min_len--;
+ } while(x);
+
+ while(min_len > 0) {
+ putchar(zero_pad ? '0' : ' ');
+ num++;
+ min_len--;
+ }
+
+ while(*bufp) {
+ putchar(*bufp++);
+ num++;
+ }
+ break;
+ }
+ }
+ return num;
+}
diff --git a/kernel/printf.h b/kernel/printf.h
new file mode 100644
index 0000000..16d612c
--- /dev/null
+++ b/kernel/printf.h
@@ -0,0 +1,6 @@
+#ifndef PRINTF_H
+#define PRINTF_H
+
+int printf(const char* format, ...);
+
+#endif
diff --git a/kernel/types.h b/kernel/types.h
index 4fdca6b..a200526 100644
--- a/kernel/types.h
+++ b/kernel/types.h
@@ -8,4 +8,6 @@ typedef unsigned short uint16_t;
typedef signed int int32_t;
typedef unsigned int uint32_t;
+typedef enum {false, true} bool;
+
#endif