aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.config1
-rw-r--r--Kconfig2
-rw-r--r--Makefile2
-rw-r--r--Makefile.config32
-rw-r--r--devices/Makefile2
-rw-r--r--devices/pckbd.c3
-rw-r--r--devices/uart.h17
-rw-r--r--devices/uart.hpp7
-rw-r--r--devices/uart_16550.c117
-rw-r--r--devices/uart_16550.cpp110
-rw-r--r--devices/vga.cpp (renamed from devices/vga.c)56
-rw-r--r--devices/vga.h33
-rw-r--r--devices/vga.hpp51
-rw-r--r--i686/sys/cpuid.h2
-rw-r--r--i686/sys/io.h23
-rw-r--r--i686/sys/io.hpp15
-rw-r--r--i686/toolchain.mk31
-rw-r--r--lib/Makefile2
-rw-r--r--lib/stdio.h26
-rw-r--r--lib/stdio/vfprintf.cpp (renamed from lib/stdio/vfprintf.c)18
-rw-r--r--lib/string.h6
-rw-r--r--rules.mk15
-rw-r--r--src/Makefile2
-rw-r--r--src/kernel.cpp (renamed from src/kernel.c)25
24 files changed, 330 insertions, 268 deletions
diff --git a/.config b/.config
index b406c20..d2c8cb9 100644
--- a/.config
+++ b/.config
@@ -3,6 +3,7 @@
# Toolchain
#
CONFIG_CFLAGS="-g -Og"
+CONFIG_CXXFLAGS="-g -Og"
CONFIG_LDFLAGS=""
# end of Toolchain
diff --git a/Kconfig b/Kconfig
index c8ce103..d50a25e 100644
--- a/Kconfig
+++ b/Kconfig
@@ -1,6 +1,8 @@
menu "Toolchain"
config CFLAGS
string "Additional C compiler flags"
+ config CXXFLAGS
+ string "Additional CXX compiler flags"
config LDFLAGS
string "Additional linker flags"
endmenu
diff --git a/Makefile b/Makefile
index 262cd97..e5afd94 100644
--- a/Makefile
+++ b/Makefile
@@ -25,6 +25,8 @@ info:
@echo " MAKE $(shell ${MAKE} --version | head -n1)"
@echo " CC $(shell ${CC} --version | head -n1)"
@echo " ${CFLAGS}"
+ @echo " CXX $(shell ${CXX} --version | head -n1)"
+ @echo " ${CXXFLAGS}"
@echo " LD $(shell ${LD} --version | head -n1)"
@echo " ${LDFLAGS}"
diff --git a/Makefile.config b/Makefile.config
index 1ea871c..42aa510 100644
--- a/Makefile.config
+++ b/Makefile.config
@@ -3,6 +3,7 @@
# Toolchain
#
CONFIG_CFLAGS="-g -Og"
+CONFIG_CXXFLAGS="-g -Og"
CONFIG_LDFLAGS=""
# end of Toolchain
@@ -25,19 +26,20 @@ CONFIG_KB_PS2=y
ARCH=i686
# define compiler, linker, archiver and strip and their flags
-#
-AS := i686-elf-as
-CC := i686-elf-gcc
-CFLAGS := -Wall -Wextra -Wpedantic -Wshadow -Wconversion -fanalyzer -ffreestanding -std=gnu11 -mgeneral-regs-only
-CFLAGS += $(shell echo ${CONFIG_CFLAGS})
-LD := i686-elf-ld
-LDFLAGS := -static -nostdlib
-LDFLAGS += $(shell echo ${CONFIG_LDFLAGS})
-AR := i686-elf-ar
-ARFLAGS := -crus
-STRIP := i686-elf-strip
-
-# test framework
-GTEST := $(shell pkg-config --cflags --libs gtest gtest_main)
-GMOCK := $(shell pkg-config --cflags --libs gmock)
+# FIXME: cpp threadsafe statics
+AS := i686-elf-as
+CC := i686-elf-gcc
+CXX := i686-elf-g++
+CFLAGS := -Wall -Wextra -Wpedantic -Wshadow -Wconversion -fanalyzer -ffreestanding -std=gnu11 \
+ -mgeneral-regs-only
+CFLAGS += $(shell echo ${CONFIG_CFLAGS})
+CXXFLAGS := -Wall -Wextra -Wpedantic -Wshadow -Wconversion -ffreestanding -std=c++17 \
+ -mgeneral-regs-only -fno-use-cxa-atexit -fno-threadsafe-statics -fno-exceptions -fno-rtti
+CXXFLAGS += $(shell echo ${CONFIG_CXXFLAGS})
+LD := i686-elf-ld
+LDFLAGS := -static -nostdlib
+LDFLAGS += $(shell echo ${CONFIG_LDFLAGS})
+AR := i686-elf-ar
+ARFLAGS := -crus
+STRIP := i686-elf-strip
diff --git a/devices/Makefile b/devices/Makefile
index 0c3a0b1..3acf31c 100644
--- a/devices/Makefile
+++ b/devices/Makefile
@@ -1,6 +1,6 @@
include ../Makefile.config
-devs.SRCS = pic_8259.c uart_16550.c vga.c i8042.c pckbd.c mouse.c
+devs.SRCS = pic_8259.c uart_16550.cpp vga.cpp i8042.c pckbd.c mouse.c
include ../rules.mk
diff --git a/devices/pckbd.c b/devices/pckbd.c
index c4fce5b..d550f91 100644
--- a/devices/pckbd.c
+++ b/devices/pckbd.c
@@ -1,6 +1,5 @@
#include "keyboard.h"
#include "ps2_controller.h"
-#include "vga.h"
#include <stdint.h>
#include <stdio.h>
#include <sys/io.h>
@@ -42,7 +41,7 @@ ps2_keyboard_irq_handler()
return;
case 0x58: // F12
- vga_clear(VGA_COLOR_LIGHT_BLUE, VGA_COLOR_LIGHT_GREY);
+ // vga_clear(VGA_COLOR_LIGHT_BLUE, VGA_COLOR_LIGHT_GREY);
return;
}
diff --git a/devices/uart.h b/devices/uart.h
deleted file mode 100644
index ee74e98..0000000
--- a/devices/uart.h
+++ /dev/null
@@ -1,17 +0,0 @@
-#pragma once
-
-// TODO #include <arch/platform.h>
-#include <stdio.h>
-
-enum UART {
- COM1 = 0x3f8,
- COM2 = 0x2f8,
- COM3 = 0x3E8,
- COM4 = 0x2E8,
- COM5 = 0x5F8,
- COM6 = 0x4F8,
- COM7 = 0x5E8,
- COM8 = 0x4E8,
-};
-
-FILE *uart_init(enum UART port);
diff --git a/devices/uart.hpp b/devices/uart.hpp
new file mode 100644
index 0000000..c86557c
--- /dev/null
+++ b/devices/uart.hpp
@@ -0,0 +1,7 @@
+#pragma once
+
+#include <stdio.h>
+#include <sys/io.h>
+
+template <UART port> FILE *uart_init();
+template <> FILE *uart_init<COM1>();
diff --git a/devices/uart_16550.c b/devices/uart_16550.c
deleted file mode 100644
index 1adcf38..0000000
--- a/devices/uart_16550.c
+++ /dev/null
@@ -1,117 +0,0 @@
-#include "uart.h"
-#include <stddef.h>
-#include <sys/io.h>
-
-enum uart_16550_offset {
- Data = 0, // read from receive buffer / write to transmit buffer | BaudDiv_l
- InterruptControl = 1, // interrupt enable | BaudDiv_h
- FifoControl = 2, // interrupt ID and FIFO control
- LineControl = 3, // most significant bit is the DLAB
- ModemControl = 4,
- LineStatus = 5,
- ModemStatus = 6,
- Scratch = 7,
-};
-// Line Control
-// | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
-// |dla| | parity | s | data |
-
-enum LineControl {
- d5bit = 0x00, // 0000 0000 data bits
- d6bit = 0x01, // 0000 0001
- d7bit = 0x02, // 0000 0010
- d8bit = 0x03, // 0000 0011
- // none = 0b00000000, // parity bits
- odd = 0x08, // 0000 1000
- even = 0x18, // 0001 1000
- mark = 0x28, // 0010 1000
- space = 0x38, // 0011 1000
- // s1bit = 0b00000000, // stop bits
- s2bit = 0x04, // 0000 0100 1.5 for 5bit data; 2 otherwise
- dlab = 0x80 // 1000 0000 divisor latch access bit
-};
-
-// Line Status Register
-enum LineStatus {
- DR = (1 << 0), // data ready: see if there is data to read
- OE = (1 << 1), // overrun error: see if there has been data lost
- PE = (1 << 2), // parity error: see if there was error in transmission
- FE = (1 << 3), // framing error: see if a stop bit was missing
- BI = (1 << 4), // break indicator: see if there is a break in data input
- THRE = (1 << 5), // transmitter holding register empty: see if transmission buffer is empty
- TEMT = (1 << 6), // transmitter empty: see if transmitter is not doing anything
- ERRO = (1 << 7), // impending error: see if there is an error with a word in the input buffer
-};
-
-int
-uart_thre(enum UART port)
-{
- return inb(port + LineStatus) & THRE;
-}
-
-void
-uart_write(const FILE *self, char a)
-{
- while (uart_thre(self->id) == 0) {}
- outb(a, self->id);
-
- if (a == '\n') {
- while (uart_thre(self->id) == 0) {}
- outb('\r', self->id);
- }
-}
-
-int
-uart_puts(const FILE *self, const char *string, int length)
-{
- int written = 0;
-
- if (length == -1)
- while (*string != '\0') {
- uart_write(self, *string);
- ++string;
- ++written;
- }
-
- else
- for (int i = 0; i < length; ++i) {
- uart_write(self, string[i]);
- ++written;
- }
-
- return written;
-}
-
-void
-uart_flush(__attribute__((unused)) 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.cpp b/devices/uart_16550.cpp
new file mode 100644
index 0000000..9620981
--- /dev/null
+++ b/devices/uart_16550.cpp
@@ -0,0 +1,110 @@
+#include "uart.hpp"
+#include <sys/io.hpp>
+
+template <UART port> struct Uart16550 : public kIoDevice, private Port<unsigned short, port> {
+ using Base = Port<unsigned short, port>;
+ using Ports = UART;
+ using PortOffset = UARTPortOffset;
+
+ // Line Control
+ // | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
+ // |dla| | parity | s | data |
+ enum LineControl : unsigned char {
+ d5bit = 0x00, // 0000 0000 data bits
+ d6bit = 0x01, // 0000 0001
+ d7bit = 0x02, // 0000 0010
+ d8bit = 0x03, // 0000 0011
+ none = 0x00, // 0000 0000 parity bits
+ odd = 0x08, // 0000 1000
+ even = 0x18, // 0001 1000
+ mark = 0x28, // 0010 1000
+ space = 0x38, // 0011 1000
+ s1bit = 0x00, // 0000 0000 stop bits
+ s2bit = 0x04, // 0000 0100 1.5 for 5bit data; 2 otherwise
+ dlab = 0x80 // 1000 0000 divisor latch access bit
+ };
+
+ // Line Status Register
+ enum LineStatus : unsigned char {
+ DR = (1 << 0), // data ready: see if there is data to read
+ OE = (1 << 1), // overrun error: see if there has been data lost
+ PE = (1 << 2), // parity error: see if there was error in transmission
+ FE = (1 << 3), // framing error: see if a stop bit was missing
+ BI = (1 << 4), // break indicator: see if there is a break in data input
+ THRE = (1 << 5), // transmitter holding register empty: see if transmission buffer is empty
+ TEMT = (1 << 6), // transmitter empty: see if transmitter is not doing anything
+ ERRO = (1 << 7), // impending error: see if there is an error with a word in the input buffer
+ };
+
+ [[nodiscard]] static bool
+ test()
+ {
+ Base::out(0x00, 1); // Disable all interrupts
+ Base::out(0x80, 3); // Enable DLAB (set baud rate divisor)
+ Base::out(0x03, 0); // Set divisor to 3 (lo byte) 38400 baud
+ Base::out(0x00, 1); // (hi byte)
+ Base::out(0x03, 3); // 8 bits, no parity, one stop bit
+ Base::out(0xc7, 2); // Enable FIFO, clear them, with 14-byte threshold
+ Base::out(0x0b, 4); // IRQs enabled, RTS/DSR set
+ Base::out(0x1e, 4); // Set in loopback mode, test the serial chip
+ Base::out(0xae, 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 (Base::in() != 0xae) { return false; }
+
+ // If serial is not faulty set it in normal operation mode
+ // (not-loopback with IRQs enabled and OUT#1 and OUT#2 bits enabled)
+ Base::out(0x0f, 4);
+ return true;
+ }
+
+ [[nodiscard]] static bool
+ thre()
+ {
+ return Base::in(PortOffset::LineStatus)&THRE;
+ }
+
+ void
+ putc(char a) override
+ {
+ while (!thre()) {}
+ Base::out(a);
+ if (a == '\n') putc('\r');
+ }
+
+ int
+ puts(const char *string, int length) override
+ {
+ int written = 0;
+
+ if (length == -1)
+ while (*string != '\0') {
+ putc(*string);
+ ++string;
+ ++written;
+ }
+
+ else {
+ for (int i = 0; i < length; ++i) putc(string[i]);
+ written += length;
+ }
+
+ return written;
+ }
+
+ void
+ flush() override
+ {
+ }
+};
+
+static_assert(sizeof(Uart16550<COM1>) == sizeof(void *));
+
+template <>
+FILE *
+uart_init<COM1>()
+{
+ static Uart16550<COM1> device;
+ return &device;
+}
diff --git a/devices/vga.c b/devices/vga.cpp
index 6d64c0a..3f83a5f 100644
--- a/devices/vga.c
+++ b/devices/vga.cpp
@@ -1,31 +1,26 @@
-#include "vga.h"
+#include "vga.hpp"
#include <stdint.h>
#include <sys/io.h>
+// FIXME user a Port
#define cga_idx_port 0x3d4
#define cga_dat_port 0x3d5
+// FIXME make constexpr
#define cursor_start 0x0a
#define cursor_end 0x0b
#define cursor_addr_h 0x0e
#define cursor_addr_l 0x0f
#define cursor_hide 0x20
-struct __attribute__((packed)) VGAEntry {
- unsigned char text;
- uint8_t foreground : 4;
- uint8_t background : 4;
-};
-_Static_assert(sizeof(struct VGAEntry) == 2, "sizeof VGAEntry");
+static_assert(sizeof(struct VGA::VGAEntry) == 2, "sizeof VGAEntry");
+// FIXME make constexpr
const int width = 80;
const int height = 25;
-struct VGAEntry *buffer;
-int col = 0;
-int row = 0;
-
// *** Cursor ***
+// FIXME make VGA members
void
vga_enable_cursor(unsigned char start, unsigned char end)
{
@@ -44,7 +39,7 @@ vga_disable_cursor()
}
void
-vga_update_cursor()
+VGA::update_cursor()
{
const uint16_t pos = row * width + col;
@@ -57,7 +52,7 @@ vga_update_cursor()
// *** Text Mode Output ***
void
-vga_putc(__attribute__((unused)) const FILE *self, char a)
+VGA::putc(char a)
{
switch (a) {
case '\n':
@@ -96,49 +91,40 @@ vga_putc(__attribute__((unused)) const FILE *self, char a)
}
int
-vga_puts(const FILE *self, const char *string, int len)
+VGA::puts(const char *string, int len)
{
int written = 0;
if (len == -1)
while (*string != '\0') {
- vga_putc(self, *string);
+ putc(*string);
++string;
++written;
}
else
for (int i = 0; i < len; ++i) {
- vga_putc(self, string[i]);
+ putc(string[i]);
++written;
}
return written;
}
-void
-vga_flush(__attribute__((unused)) const FILE *self)
+// *** Text Mode ***
+VGA::VGA(void *addr)
{
- vga_update_cursor();
+ buffer = (struct VGAEntry *)addr;
+ vga_enable_cursor(14, 15);
+ clear(VGA_COLOR_LIGHT_BLUE, VGA_COLOR_LIGHT_GREY);
}
-
-// *** Text Mode ***
-FILE vga_stream;
-
FILE *
-vga_init()
+vga_init(void *buffer)
{
- 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;
+ static VGA device(buffer);
+ return &device;
}
void
-vga_clear(enum vga_color foreground, enum vga_color background)
+VGA::clear(enum vga_color foreground, enum vga_color background)
{
for (int y = 0; y < height; ++y)
for (int x = 0; x < width; ++x) {
@@ -148,5 +134,5 @@ vga_clear(enum vga_color foreground, enum vga_color background)
buffer[index].background = background;
}
col = row = 0;
- vga_update_cursor();
+ update_cursor();
}
diff --git a/devices/vga.h b/devices/vga.h
deleted file mode 100644
index d9dfd44..0000000
--- a/devices/vga.h
+++ /dev/null
@@ -1,33 +0,0 @@
-#pragma once
-
-#include <stdio.h>
-
-/** Hardware text mode color constants. */
-enum vga_color {
- VGA_COLOR_BLACK = 0,
- VGA_COLOR_BLUE = 1,
- VGA_COLOR_GREEN = 2,
- VGA_COLOR_CYAN = 3,
- VGA_COLOR_RED = 4,
- VGA_COLOR_MAGENTA = 5,
- VGA_COLOR_BROWN = 6,
- VGA_COLOR_LIGHT_GREY = 7,
- VGA_COLOR_DARK_GREY = 8,
- VGA_COLOR_LIGHT_BLUE = 9,
- VGA_COLOR_LIGHT_GREEN = 10,
- VGA_COLOR_LIGHT_CYAN = 11,
- VGA_COLOR_LIGHT_RED = 12,
- VGA_COLOR_LIGHT_MAGENTA = 13,
- VGA_COLOR_LIGHT_BROWN = 14,
- VGA_COLOR_WHITE = 15,
-};
-
-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_enable_cursor(unsigned char start, unsigned char end);
-// void vga_disable_cursor();
-void vga_update_cursor();
diff --git a/devices/vga.hpp b/devices/vga.hpp
new file mode 100644
index 0000000..5287d73
--- /dev/null
+++ b/devices/vga.hpp
@@ -0,0 +1,51 @@
+#pragma once
+
+#include <stdio.h>
+
+/** Hardware text mode color constants. */
+enum vga_color {
+ VGA_COLOR_BLACK = 0,
+ VGA_COLOR_BLUE = 1,
+ VGA_COLOR_GREEN = 2,
+ VGA_COLOR_CYAN = 3,
+ VGA_COLOR_RED = 4,
+ VGA_COLOR_MAGENTA = 5,
+ VGA_COLOR_BROWN = 6,
+ VGA_COLOR_LIGHT_GREY = 7,
+ VGA_COLOR_DARK_GREY = 8,
+ VGA_COLOR_LIGHT_BLUE = 9,
+ VGA_COLOR_LIGHT_GREEN = 10,
+ VGA_COLOR_LIGHT_CYAN = 11,
+ VGA_COLOR_LIGHT_RED = 12,
+ VGA_COLOR_LIGHT_MAGENTA = 13,
+ VGA_COLOR_LIGHT_BROWN = 14,
+ VGA_COLOR_WHITE = 15,
+};
+
+FILE *vga_init(void *buffer);
+
+struct VGA : public kIoDevice {
+ VGA(void *addr);
+
+ void putc(char a) override;
+ int puts(const char *string, int length) override;
+ void
+ flush() override
+ {
+ update_cursor();
+ }
+
+ struct __attribute__((packed)) VGAEntry {
+ unsigned char text;
+ unsigned char foreground : 4;
+ unsigned char background : 4;
+ };
+
+private:
+ void clear(enum vga_color foreground, enum vga_color background);
+ void update_cursor();
+
+ struct VGAEntry *buffer;
+ int col = 0;
+ int row = 0;
+};
diff --git a/i686/sys/cpuid.h b/i686/sys/cpuid.h
index 862601f..65b43c6 100644
--- a/i686/sys/cpuid.h
+++ b/i686/sys/cpuid.h
@@ -12,7 +12,7 @@ struct CPUVersion {
unsigned int family_ex : 8;
unsigned int __unused_2 : 4;
} __attribute__((packed, aligned(__alignof__(unsigned int))));
-_Static_assert(sizeof(struct CPUVersion) == sizeof(unsigned int), "cpuid version struct size");
+// FIXME _Static_assert(sizeof(struct CPUVersion) == sizeof(unsigned int), "cpuid version struct size");
unsigned int
family(const struct CPUVersion v)
diff --git a/i686/sys/io.h b/i686/sys/io.h
index 74d4950..b6c24c5 100644
--- a/i686/sys/io.h
+++ b/i686/sys/io.h
@@ -1,5 +1,27 @@
#pragma once
+// port listings
+enum UART {
+ COM1 = 0x3f8,
+ COM2 = 0x2f8,
+ COM3 = 0x3e8,
+ COM4 = 0x2e8,
+ COM5 = 0x5f8,
+ COM6 = 0x4f8,
+ COM7 = 0x5e8,
+ COM8 = 0x4e8,
+};
+enum UARTPortOffset {
+ Data = 0, // read from receive buffer / write to transmit buffer | BaudDiv_l
+ InterruptControl = 1, // interrupt enable | BaudDiv_h
+ FifoControl = 2, // interrupt ID and FIFO control
+ LineControl = 3, // most significant bit is the DLAB
+ ModemControl = 4,
+ LineStatus = 5,
+ ModemStatus = 6,
+ Scratch = 7,
+};
+
static inline void
outb(unsigned char val, unsigned short port)
{
@@ -77,3 +99,4 @@ insl(unsigned short port, void *__buf, unsigned long __n)
{
asm volatile("cld; rep; insl" : "+D"(__buf), "+c"(__n) : "d"(port));
}
+
diff --git a/i686/sys/io.hpp b/i686/sys/io.hpp
new file mode 100644
index 0000000..bea9323
--- /dev/null
+++ b/i686/sys/io.hpp
@@ -0,0 +1,15 @@
+#pragma once
+
+template <typename T, unsigned short port> struct Port {
+ static void
+ out(T val, unsigned short offset = 0)
+ {
+ outb(val, port + offset);
+ }
+
+ static auto
+ in(unsigned short offset = 0)
+ {
+ return inb(port + offset);
+ }
+};
diff --git a/i686/toolchain.mk b/i686/toolchain.mk
index 43c758c..ae2fb35 100644
--- a/i686/toolchain.mk
+++ b/i686/toolchain.mk
@@ -1,19 +1,20 @@
ARCH=i686
# define compiler, linker, archiver and strip and their flags
-#
-AS := i686-elf-as
-CC := i686-elf-gcc
-CFLAGS := -Wall -Wextra -Wpedantic -Wshadow -Wconversion -fanalyzer -ffreestanding -std=gnu11 -mgeneral-regs-only
-CFLAGS += $(shell echo ${CONFIG_CFLAGS})
-LD := i686-elf-ld
-LDFLAGS := -static -nostdlib
-LDFLAGS += $(shell echo ${CONFIG_LDFLAGS})
-AR := i686-elf-ar
-ARFLAGS := -crus
-STRIP := i686-elf-strip
-
-# test framework
-GTEST := $(shell pkg-config --cflags --libs gtest gtest_main)
-GMOCK := $(shell pkg-config --cflags --libs gmock)
+# FIXME: cpp threadsafe statics
+AS := i686-elf-as
+CC := i686-elf-gcc
+CXX := i686-elf-g++
+CFLAGS := -Wall -Wextra -Wpedantic -Wshadow -Wconversion -fanalyzer -ffreestanding -std=gnu11 \
+ -mgeneral-regs-only
+CFLAGS += $(shell echo ${CONFIG_CFLAGS})
+CXXFLAGS := -Wall -Wextra -Wpedantic -Wshadow -Wconversion -ffreestanding -std=c++17 \
+ -mgeneral-regs-only -fno-use-cxa-atexit -fno-threadsafe-statics -fno-exceptions -fno-rtti
+CXXFLAGS += $(shell echo ${CONFIG_CXXFLAGS})
+LD := i686-elf-ld
+LDFLAGS := -static -nostdlib
+LDFLAGS += $(shell echo ${CONFIG_LDFLAGS})
+AR := i686-elf-ar
+ARFLAGS := -crus
+STRIP := i686-elf-strip
diff --git a/lib/Makefile b/lib/Makefile
index 68d1e74..b3e1f66 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -1,6 +1,6 @@
include ../Makefile.config
-libk.SRCS = stdio/printf.c stdio/fprintf.c stdio/vfprintf.c \
+libk.SRCS = stdio/printf.c stdio/fprintf.c stdio/vfprintf.cpp \
stdlib/memcpy.c stdlib/memset.c \
string/itoa.c
diff --git a/lib/stdio.h b/lib/stdio.h
index f7c1846..9a0c41e 100644
--- a/lib/stdio.h
+++ b/lib/stdio.h
@@ -2,16 +2,20 @@
#include <stdarg.h>
+#ifdef __cplusplus
/** An object type used for streams */
-typedef struct kIoDevice {
- int id;
- /** Functions that prints a character to the stream */
- void (*putc)(const struct kIoDevice *, char);
+struct kIoDevice {
+ /** Function that prints a character to the stream */
+ virtual void putc(char) = 0;
/** Function that prints a string to the stream */
- int (*puts)(const struct kIoDevice *, const char *, int);
- /** Flush all buffers */
- void (*flush)(const struct kIoDevice *);
-} FILE;
+ virtual int puts(const char *, int) = 0;
+ /** Flush write buffers */
+ virtual void flush() = 0;
+};
+typedef kIoDevice FILE;
+#else
+typedef void FILE;
+#endif
/** A FILE value corresponding to stdin, the keyboard buffer */
extern FILE *stdin;
@@ -20,6 +24,9 @@ extern FILE *stdout;
/** A FILE value corresponding to stderr, the uart */
extern FILE *stderr;
+#ifdef __cplusplus
+extern "C" {
+#endif
/**
* Write the formatted string to stdout
*
@@ -36,3 +43,6 @@ 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);
+#ifdef __cplusplus
+}
+#endif
diff --git a/lib/stdio/vfprintf.c b/lib/stdio/vfprintf.cpp
index d24e43e..aa9256d 100644
--- a/lib/stdio/vfprintf.c
+++ b/lib/stdio/vfprintf.cpp
@@ -3,7 +3,7 @@
static char buffer[3 * sizeof(int) + 2];
-int
+extern "C" int
vfprintf(FILE *restrict stream, const char *restrict format, va_list params)
{
int written = 0;
@@ -12,31 +12,31 @@ vfprintf(FILE *restrict stream, const char *restrict format, va_list params)
int l = 0;
for (int i = 0; format[i] != '\0'; ++i) {
if (format[i] == '%') {
- written += stream->puts(stream, &format[s], l);
+ written += stream->puts(&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);
+ written += stream->puts(arg, -1);
} break;
case 'c': {
const int arg = va_arg(params, int);
- stream->putc(stream, arg);
+ stream->putc(arg);
++written;
} break;
case 'd': {
const char *arg = itoa(buffer, va_arg(params, int), 10);
- written += stream->puts(stream, arg, -1);
+ written += stream->puts(arg, -1);
} break;
case 'u': {
const char *arg = utoa(buffer, va_arg(params, unsigned int), 10);
- written += stream->puts(stream, arg, -1);
+ written += stream->puts(arg, -1);
} break;
case 'x': {
const char *arg = utoa(buffer, va_arg(params, unsigned int), 16);
- written += stream->puts(stream, arg, -1);
+ written += stream->puts(arg, -1);
} break;
}
@@ -47,8 +47,8 @@ vfprintf(FILE *restrict stream, const char *restrict format, va_list params)
++l;
}
- if (l > 0) { written += stream->puts(stream, &format[s], l); }
+ if (l > 0) { written += stream->puts(&format[s], l); }
- stream->flush(stream);
+ stream->flush();
return written;
}
diff --git a/lib/string.h b/lib/string.h
index 1eb3da2..460057c 100644
--- a/lib/string.h
+++ b/lib/string.h
@@ -4,6 +4,9 @@
#define DECIMAL 10
#define HEX 16
+#ifdef __cplusplus
+extern "C" {
+#endif
/**
* Convert int into a string
*/
@@ -12,3 +15,6 @@ char *itoa(char *p, int x, int base);
* Convert unsigned int into a string
*/
char *utoa(char *p, unsigned x, int base);
+#ifdef __cplusplus
+}
+#endif
diff --git a/rules.mk b/rules.mk
index ada9789..14023da 100644
--- a/rules.mk
+++ b/rules.mk
@@ -6,7 +6,8 @@ $(foreach V,$(filter %.SRCS, ${.VARIABLES}),\
)
# extra flags
-CFLAGS += -isysteminclude -I../lib
+CFLAGS += -isysteminclude -I../lib
+CXXFLAGS += -isysteminclude -I../lib -Drestrict=__restrict__
# Suffix rules
%.a:
@@ -26,10 +27,18 @@ CFLAGS += -isysteminclude -I../lib
@echo ' CC $^'
@$(CC) $(CFLAGS) -c -o $@ $^
+.cpp.o:
+ @echo ' CXX $^'
+ @$(CXX) $(CXXFLAGS) -c -o $@ $^
+
# Test rules
+TEST_CXX := c++
+GTEST := $(shell pkg-config --cflags --libs gtest gtest_main)
+GMOCK := $(shell pkg-config --cflags --libs gmock)
+
tst/test_%: tst/%.cc
- @echo ' CXX $@'
- @${CXX} $< -o $@ $(GTEST) $(GMOCK)
+ @echo ' CXX TEST $@'
+ @$(TEST_CXX) $< -o $@ $(GTEST) $(GMOCK)
# clean target
.PHONY: clean FORCE
diff --git a/src/Makefile b/src/Makefile
index de59cfb..637f9a1 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -1,6 +1,6 @@
include ../Makefile.config
-kernel.SRCS := multiboot2.c mmap.c kernel.c mem/vmm.c
+kernel.SRCS := multiboot2.c mmap.c kernel.cpp mem/vmm.c
kernel.OBJS := conf.h
include ../rules.mk
diff --git a/src/kernel.c b/src/kernel.cpp
index b8432a8..751bcb0 100644
--- a/src/kernel.c
+++ b/src/kernel.cpp
@@ -4,24 +4,29 @@
// description: kernel entry point
//=====================================================================
+extern "C" {
#include "conf.h"
-#include "devices/keyboard.h"
-#include "devices/mouse.h"
-#include "devices/pic.h"
-#include "devices/ps2_controller.h"
-#include "devices/uart.h"
-#include "devices/vga.h"
#include "mem.h"
+#include <devices/keyboard.h>
+#include <devices/mouse.h>
+#include <devices/pic.h>
+#include <devices/ps2_controller.h>
#include <stdio.h>
#include <sys/cpuid.h>
+}
+#include <devices/uart.hpp>
+#include <devices/vga.hpp>
FILE *stdin;
FILE *stdout;
FILE *stderr;
-void kmain() {
- stderr = uart_init(COM1);
- stdout = vga_init(vmm_map(0xb8000, 0xc03ff000));
+extern "C" void
+kmain()
+{
+ stderr = uart_init<COM1>();
+ vmm_map(0xb8000, 0xc03ff000);
+ stdout = vga_init((void *)0xc03ff000);
printf("glitch [version " VERSION "] [" CC "]\n");
fprintf(stderr, "glitch [version " VERSION "] [" CC "]\n");
@@ -42,7 +47,7 @@ void kmain() {
mouse_init();
pic_enable();
- printf("interrupts enabled\n");
+ fprintf(stderr, "interrupts enabled\n");
/*
alloc4M();