summaryrefslogtreecommitdiffhomepage
path: root/src/loader
diff options
context:
space:
mode:
authorMarvin Borner2021-07-04 21:31:28 +0200
committerMarvin Borner2021-07-04 21:34:15 +0200
commit9b8698769535846d029c44247956eed9a21f1185 (patch)
tree294a17af4102805ab9863274339e8e030897804e /src/loader
Initial commit
Diffstat (limited to 'src/loader')
-rw-r--r--src/loader/cpu.c26
-rw-r--r--src/loader/inc/cpu.h13
-rw-r--r--src/loader/inc/def.h28
-rw-r--r--src/loader/inc/lib.h14
-rw-r--r--src/loader/inc/log.h11
-rw-r--r--src/loader/lib.c85
-rw-r--r--src/loader/link.ld35
-rw-r--r--src/loader/log.c108
-rw-r--r--src/loader/main.c19
9 files changed, 339 insertions, 0 deletions
diff --git a/src/loader/cpu.c b/src/loader/cpu.c
new file mode 100644
index 0000000..a12d2fa
--- /dev/null
+++ b/src/loader/cpu.c
@@ -0,0 +1,26 @@
+// MIT License, Copyright (c) 2021 Marvin Borner
+
+#include <cpu.h>
+
+/**
+ * CPU IO
+ */
+
+u8 inb(u16 port)
+{
+ u8 value;
+ __asm__ volatile("inb %1, %0" : "=a"(value) : "Nd"(port));
+ return value;
+}
+
+u16 inw(u16 port)
+{
+ u16 value;
+ __asm__ volatile("inw %1, %0" : "=a"(value) : "Nd"(port));
+ return value;
+}
+
+void outb(u16 port, u8 data)
+{
+ __asm__ volatile("outb %0, %1" ::"a"(data), "Nd"(port));
+}
diff --git a/src/loader/inc/cpu.h b/src/loader/inc/cpu.h
new file mode 100644
index 0000000..88db34b
--- /dev/null
+++ b/src/loader/inc/cpu.h
@@ -0,0 +1,13 @@
+// MIT License, Copyright (c) 2021 Marvin Borner
+
+#ifndef CPU_H
+#define CPU_H
+
+#include <def.h>
+
+u8 inb(u16 port);
+u16 inw(u16 port);
+
+void outb(u16 port, u8 data);
+
+#endif
diff --git a/src/loader/inc/def.h b/src/loader/inc/def.h
new file mode 100644
index 0000000..8c2f9aa
--- /dev/null
+++ b/src/loader/inc/def.h
@@ -0,0 +1,28 @@
+// MIT License, Copyright (c) 2021 Marvin Borner
+// Useful macros/types
+
+#ifndef DEF_H
+#define DEF_H
+
+typedef signed char s8;
+typedef unsigned char u8;
+
+typedef signed short s16;
+typedef unsigned short u16;
+
+typedef signed int s32;
+typedef unsigned int u32;
+
+typedef __builtin_va_list va_list;
+#define va_start __builtin_va_start
+#define va_end __builtin_va_end
+#define va_arg __builtin_va_arg
+
+#define NULL ((void *)0)
+#define MIN(a, b) (((a) < (b)) ? (a) : (b))
+#define MAX(a, b) (((a) > (b)) ? (a) : (b))
+#define ABS(a) (((a) < 0) ? -(a) : (a))
+
+#define PACKED __attribute__((packed))
+
+#endif
diff --git a/src/loader/inc/lib.h b/src/loader/inc/lib.h
new file mode 100644
index 0000000..997db67
--- /dev/null
+++ b/src/loader/inc/lib.h
@@ -0,0 +1,14 @@
+// MIT License, Copyright (c) 2021 Marvin Borner
+
+#ifndef LIB_H
+#define LIB_H
+
+#include <def.h>
+
+u32 strlen(const char *str);
+u32 strnlen(const char *s, u32 max);
+u32 strlcpy(char *dst, const char *src, u32 size);
+
+int itoa(s32 value, char *buffer, u32 base);
+
+#endif
diff --git a/src/loader/inc/log.h b/src/loader/inc/log.h
new file mode 100644
index 0000000..2d65a76
--- /dev/null
+++ b/src/loader/inc/log.h
@@ -0,0 +1,11 @@
+// MIT License, Copyright (c) 2021 Marvin Borner
+
+#ifndef LOG_H
+#define LOG_H
+
+void serial_install(void);
+void serial_print(const char *data);
+
+void log(const char *format, ...);
+
+#endif
diff --git a/src/loader/lib.c b/src/loader/lib.c
new file mode 100644
index 0000000..c54ef14
--- /dev/null
+++ b/src/loader/lib.c
@@ -0,0 +1,85 @@
+// MIT License, Copyright (c) 2021 Marvin Borner
+
+#include <lib.h>
+
+/**
+ * Common string functions
+ */
+
+u32 strlen(const char *str)
+{
+ const char *s = str;
+ while (*s)
+ s++;
+ return s - str;
+}
+
+u32 strnlen(const char *str, u32 max)
+{
+ const char *s = str;
+ while (max && *s) {
+ s++;
+ max--;
+ }
+ return s - str;
+}
+
+u32 strlcpy(char *dst, const char *src, u32 size)
+{
+ const char *orig = src;
+ u32 left = size;
+
+ if (left)
+ while (--left)
+ if (!(*dst++ = *src++))
+ break;
+
+ if (!left) {
+ if (size)
+ *dst = 0;
+ while (*src++)
+ ;
+ }
+
+ return src - orig - 1;
+}
+
+/**
+ * Conversion
+ */
+
+int itoa(s32 value, char *buffer, u32 base)
+{
+ char tmp[16];
+ char *tp = tmp;
+ int i;
+ unsigned v;
+
+ int sign = (base == 10 && value < 0);
+ if (sign)
+ v = -value;
+ else
+ v = (unsigned)value;
+
+ while (v || tp == tmp) {
+ i = v % base;
+ v /= base;
+ if (i < 10)
+ *tp++ = i + '0';
+ else
+ *tp++ = i + 'a' - 10;
+ }
+
+ int len = tp - tmp;
+
+ if (sign) {
+ *buffer++ = '-';
+ len++;
+ }
+
+ while (tp > tmp)
+ *buffer++ = *--tp;
+ *buffer = '\0';
+
+ return len;
+}
diff --git a/src/loader/link.ld b/src/loader/link.ld
new file mode 100644
index 0000000..aa97f49
--- /dev/null
+++ b/src/loader/link.ld
@@ -0,0 +1,35 @@
+/* MIT License, Copyright (c) 2021 Marvin Borner */
+
+OUTPUT_FORMAT("elf32-i386")
+OUTPUT_ARCH(i386)
+ENTRY(start)
+phys = 0x7e00;
+
+SECTIONS
+{
+ . = phys;
+
+ .text :
+ {
+ *(.text.start)
+ *(.text*)
+ }
+
+ .rodata :
+ {
+ *(.rodata*)
+ }
+
+ .data :
+ {
+ *(.data*)
+ }
+
+ .bss :
+ {
+ *(COMMON)
+ *(.bss)
+ }
+
+ end = .;
+}
diff --git a/src/loader/log.c b/src/loader/log.c
new file mode 100644
index 0000000..a2c05f0
--- /dev/null
+++ b/src/loader/log.c
@@ -0,0 +1,108 @@
+#include <cpu.h>
+#include <lib.h>
+#include <log.h>
+
+/**
+ * Formatting
+ */
+
+static u32 vsnprintf(char *str, u32 size, const char *format, va_list ap)
+{
+ u32 length = 0;
+
+ int temp_int;
+ char temp_ch;
+ char *temp_str;
+
+ char buffer[64] = { 0 };
+
+ // TODO: Fix potential memory overflows because of str[length++]=xxx
+ char ch;
+ while ((ch = *format++)) {
+ if (ch == '%') {
+ switch (*format++) {
+ case '%':
+ str[length++] = '%';
+ break;
+ case 'c':
+ temp_ch = va_arg(ap, int);
+ str[length++] = temp_ch;
+ break;
+ case 's':
+ temp_str = va_arg(ap, char *);
+ length += strlcpy(&str[length], temp_str, size - length);
+ break;
+ case 'b':
+ temp_int = va_arg(ap, int);
+ itoa(temp_int, buffer, 2);
+ length += strlcpy(&str[length], buffer, size - length);
+ break;
+ case 'd':
+ temp_int = va_arg(ap, int);
+ itoa(temp_int, buffer, 10);
+ length += strlcpy(&str[length], buffer, size - length);
+ break;
+ case 'x':
+ temp_int = va_arg(ap, int);
+ itoa(temp_int, buffer, 16);
+ length += strlcpy(&str[length], buffer, size - length);
+ break;
+ default:
+ serial_print("Unknown printf format\n");
+ }
+ } else {
+ str[length++] = ch;
+ }
+ }
+
+ return length;
+}
+
+/**
+ * Serial
+ */
+
+void serial_install(void)
+{
+ outb(0x3f8 + 1, 0x00);
+ outb(0x3f8 + 3, 0x80);
+ outb(0x3f8 + 0, 0x03);
+ outb(0x3f8 + 1, 0x00);
+ outb(0x3f8 + 3, 0x03);
+ outb(0x3f8 + 2, 0xc7);
+ outb(0x3f8 + 4, 0x0B);
+}
+
+static int is_transmit_empty(void)
+{
+ return inb(0x3f8 + 5) & 0x20;
+}
+
+static void serial_put(char ch)
+{
+ while (is_transmit_empty() == 0)
+ ;
+ outb(0x3f8, (u8)ch);
+}
+
+void serial_print(const char *data)
+{
+ for (const char *p = data; *p; p++)
+ serial_put(*p);
+}
+
+/**
+ * Universal print function
+ */
+
+void log(const char *format, ...)
+{
+ char buf[1024] = { 0 };
+
+ va_list ap;
+ va_start(ap, format);
+ vsnprintf(buf, sizeof(buf), format, ap);
+ va_end(ap);
+
+ serial_print(buf);
+}
diff --git a/src/loader/main.c b/src/loader/main.c
new file mode 100644
index 0000000..54b5122
--- /dev/null
+++ b/src/loader/main.c
@@ -0,0 +1,19 @@
+// MIT License, Copyright (c) 2021 Marvin Borner
+
+#include <def.h>
+#include <log.h>
+
+/**
+ * Entry
+ */
+
+int start(void);
+int start(void)
+{
+ serial_install();
+ log("Hello %d\n", 42);
+
+ while (1)
+ ;
+ return 0;
+}