diff options
author | Marvin Borner | 2021-07-04 21:31:28 +0200 |
---|---|---|
committer | Marvin Borner | 2021-07-04 21:34:15 +0200 |
commit | 9b8698769535846d029c44247956eed9a21f1185 (patch) | |
tree | 294a17af4102805ab9863274339e8e030897804e /src/loader |
Initial commit
Diffstat (limited to 'src/loader')
-rw-r--r-- | src/loader/cpu.c | 26 | ||||
-rw-r--r-- | src/loader/inc/cpu.h | 13 | ||||
-rw-r--r-- | src/loader/inc/def.h | 28 | ||||
-rw-r--r-- | src/loader/inc/lib.h | 14 | ||||
-rw-r--r-- | src/loader/inc/log.h | 11 | ||||
-rw-r--r-- | src/loader/lib.c | 85 | ||||
-rw-r--r-- | src/loader/link.ld | 35 | ||||
-rw-r--r-- | src/loader/log.c | 108 | ||||
-rw-r--r-- | src/loader/main.c | 19 |
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; +} |