diff options
author | Your Name <you@example.com> | 2020-06-22 17:06:46 +0200 |
---|---|---|
committer | Your Name <you@example.com> | 2020-06-22 17:06:46 +0200 |
commit | 6bacc4f30752e49733d6efb219d58eb4745a49a9 (patch) | |
tree | b1459f86e5b5b0c2ad2fe81e1b96ad588de463d7 | |
download | pOS-6bacc4f30752e49733d6efb219d58eb4745a49a9.tar.gz pOS-6bacc4f30752e49733d6efb219d58eb4745a49a9.tar.bz2 pOS-6bacc4f30752e49733d6efb219d58eb4745a49a9.zip |
Git commit clean
41 files changed, 1426 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ee55692 --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +out/ +build/ + +pOS.config +pOS.creator +pOS.creator.user +pOS.cflags +pOS.cxxflags +pOS.files +pOS.includes diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..1dd6723 --- /dev/null +++ b/Makefile @@ -0,0 +1,9 @@ +all: src/ + cd src && make -f .Makefile && cd .. + +run: all + @echo -e "\033[32m" + @qemu-system-i386 -kernel out/pOS.bin -serial stdio + @echo -e "\033[0;39m" +clean: + rm -rf out diff --git a/README.md b/README.md new file mode 100644 index 0000000..a0a81b3 --- /dev/null +++ b/README.md @@ -0,0 +1,7 @@ +# pOS - x86 Testing OS + +## Build +`make` + +## Run +`make run` diff --git a/TODO b/TODO new file mode 100644 index 0000000..bc64800 --- /dev/null +++ b/TODO @@ -0,0 +1,4 @@ +[] Write x86 bootloader +[] Add interrupts +[] More cpp features +[] Code cleanup diff --git a/src/.Makefile b/src/.Makefile new file mode 100644 index 0000000..e750f23 --- /dev/null +++ b/src/.Makefile @@ -0,0 +1,4 @@ +all: pOS.bin + +pOS.bin: ./.build.sh + ./.build.sh diff --git a/src/.build.sh b/src/.build.sh new file mode 100755 index 0000000..fde3c02 --- /dev/null +++ b/src/.build.sh @@ -0,0 +1,17 @@ +out_dir="..\/out" +include="-I pOS/include -I pOS/include/libc" + +mkdir $out_dir 2> /dev/null + +for f in $(find pOS/ -type f \( -iname \*.cpp -o -iname \*.c \)) +do + out_file=$(echo $f | sed 's/pOS/..\/out\/pOS/g' | sed 's/\.cpp/\.o/g' | sed 's/\.c/\.o/g') + mkdir -p $(dirname $out_file) + i686-elf-g++ $include -g -std=c++11 -c $f -o $out_file -ffreestanding -O2 -Wall -Wextra -fno-exceptions -fno-rtti +done + +mkdir -p ../out/bootloader + +nasm -f elf32 bootloader/boot.s -o ../out/bootloader/boot.o + +i686-elf-g++ -T linker.ld -o ../out/pOS.bin -ffreestanding -O2 -nostdlib $(find ../out -type f -name "*.o") -lgcc diff --git a/src/bootloader/boot.s b/src/bootloader/boot.s new file mode 100644 index 0000000..0bb10d5 --- /dev/null +++ b/src/bootloader/boot.s @@ -0,0 +1,33 @@ +; Multiboot header +MBALIGN equ 1 << 0 +MEMINFO equ 1 << 1 +FLAGS equ MBALIGN | MEMINFO +MAGIC equ 0x1BADB002 +CHECKSUM equ -(MAGIC + FLAGS) + +section .multiboot +align 4 + dd MAGIC + dd FLAGS + dd CHECKSUM + +; Setup stack +section .bss +align 16 +stack_bottom: +resb 16384 ; 16 KiB +stack_top: + +section .text +global _start:function (_start.end - _start) +_start: + ; Initialize stack + mov esp, stack_top + + extern kmain + call kmain + + cli +.inf: hlt + jmp .inf +.end: diff --git a/src/linker.ld b/src/linker.ld new file mode 100644 index 0000000..141428c --- /dev/null +++ b/src/linker.ld @@ -0,0 +1,28 @@ +ENTRY(_start) +SECTIONS +{ + . = 1M; + + /* Multiboot header */ + .text BLOCK(4K) : ALIGN(4K) + { + *(.multiboot) + *(.text) + } + + .rodata BLOCK(4K) : ALIGN(4K) + { + *(.rodata) + } + + .data BLOCK(4K) : ALIGN(4K) + { + *(.data) + } + + .bss BLOCK(4K) : ALIGN(4K) + { + *(COMMON) + *(.bss) + } +} diff --git a/src/pOS/arch/x86/kernel/debug.cpp b/src/pOS/arch/x86/kernel/debug.cpp new file mode 100644 index 0000000..43c81c7 --- /dev/null +++ b/src/pOS/arch/x86/kernel/debug.cpp @@ -0,0 +1,27 @@ +#include <kernel/debug.h> + +static void debugger_out(char c) +{ + Serial::serial_putch(c); +} + +static void debugger_putch(char*&, char c) //wrapper so that we can sprintf +{ + debugger_out(c); +} + +int dbgprint(const char* str, int len) +{ + for (int i = 0; i < len; ++i) + debugger_out(str[i]); + return 0; +} + +int dbgprintf(const char* fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + int ret = printf_internal(debugger_putch, nullptr, fmt, ap); + va_end(ap); + return ret; +} diff --git a/src/pOS/arch/x86/kernel/rtc.cpp b/src/pOS/arch/x86/kernel/rtc.cpp new file mode 100644 index 0000000..ab64a90 --- /dev/null +++ b/src/pOS/arch/x86/kernel/rtc.cpp @@ -0,0 +1,36 @@ +#include <kernel/rtc.h> + +int RTC::get_update_in_progress_flag(void) +{ + System::outb(CMOS_PORT, 0x0A); + return (System::inb(CMOS_DATA) & 0x80); +} + +uint8_t RTC::read_cmos(uint8_t registr) +{ + uint8_t result; + System::outb(CMOS_PORT, registr); + do + result = System::inb(CMOS_DATA); + while(RTC::get_update_in_progress_flag()); + + System::outb(CMOS_PORT, 0x0B); + if(!(System::inb(CMOS_DATA) & 0x04)) //to binary + result = (result & 0x0F) + ((result/ 16) * 10); + + return result; +} + +timedate RTC::get_date(void) +{ + return timedate { + RTC::read_cmos(CMOS_READ_SECOND), + RTC::read_cmos(CMOS_READ_MINUTE), + RTC::read_cmos(CMOS_READ_HOUR), + RTC::read_cmos(CMOS_READ_DAY), + RTC::read_cmos(CMOS_READ_MONTH), + RTC::read_cmos(CMOS_READ_YEAR), + CURRENT_CENTURY, + CURRENT_MILLENNIUM + }; +} diff --git a/src/pOS/arch/x86/kernel/serial.cpp b/src/pOS/arch/x86/kernel/serial.cpp new file mode 100644 index 0000000..2dd0358 --- /dev/null +++ b/src/pOS/arch/x86/kernel/serial.cpp @@ -0,0 +1,64 @@ +#include <kernel/serial.h> + +int Serial::init_serial(uint16_t port) +{ + System::outb(port + 1, 0x00); //cli + System::outb(port + 3, 0x80); + System::outb(port + 0, 0x03); + System::outb(port + 1, 0x00); + System::outb(port + 3, 0x03); + System::outb(port + 2, 0xC7); + System::outb(port + 4, 0x0B); //sti + + return 0; +} + +int Serial::is_transmit_empty(uint16_t port) +{ + return System::inb(port + 5) & 0x20; +} + +int Serial::write_serial(uint8_t data, uint16_t port) +{ + while (!is_transmit_empty(port)); + + System::outb(port, data); + + return 0; +} + +int Serial::serial_received(uint16_t port) +{ + return System::inb(port + 5) & 1; +} + +uint8_t Serial::read_serial(uint16_t port) +{ + while (!serial_received(port)); + + return System::inb(port); +} + +int Serial::serial_putch(char c) +{ + static bool serial_ready = false; + static bool was_cr = false; + + if (!serial_ready) + { + init_serial(COM1_PORT); + serial_ready = true; + } + + if (c == '\n' && !was_cr) + write_serial('\r', COM1_PORT); + + write_serial(c, COM1_PORT); + + if (c == '\r') + was_cr = true; + else + was_cr = false; + + return 0; +} diff --git a/src/pOS/arch/x86/kernel/system.cpp b/src/pOS/arch/x86/kernel/system.cpp new file mode 100644 index 0000000..ade04f8 --- /dev/null +++ b/src/pOS/arch/x86/kernel/system.cpp @@ -0,0 +1,21 @@ +#include <kernel/system.h> + +uint8_t System::inb(uint16_t port) +{ + uint8_t result; + asm volatile( "inb %1, %0" : "=a"(result) : "Nd"(port)); + return result; +} + +void System::outb(uint16_t port, uint8_t data) +{ + asm volatile( "outb %0, %1" : : "a"(data), "Nd"(port)); +} + +int System::idle_loop(void) +{ + while(1) + asm("hlt"); + + return 1; +} diff --git a/src/pOS/arch/x86/kernel/time.cpp b/src/pOS/arch/x86/kernel/time.cpp new file mode 100644 index 0000000..b0e50b9 --- /dev/null +++ b/src/pOS/arch/x86/kernel/time.cpp @@ -0,0 +1,134 @@ +#include <kernel/time.h> + +static constexpr const char* months[12] = { + "January", + "Febuary", + "March", + "April", + "May", + "June", + "July", + "August", + "September", + "October", + "November", + "December" +}; + +static constexpr const char* days[7] = { + "Monday", + "Tuesday", + "Wednesday", + "Thursday", + "Friday", + "Saturday", + "Sunday" +}; + +timedate Time::get_date(void) +{ + return RTC::get_date(); +} + +uint8_t Time::get_second(void) +{ + return Time::get_date().second; +} + +uint8_t Time::get_minute(void) +{ + return Time::get_date().minute; +} + +uint8_t Time::get_hour(void) +{ + return Time::get_date().hour; +} + +uint8_t Time::get_day(void) +{ + return Time::get_date().day; +} + +uint8_t Time::get_month(void) +{ + return Time::get_date().month; +} + +uint8_t Time::get_year(void) +{ + return Time::get_date().year; +} + +uint8_t Time::get_century(void) +{ + return Time::get_date().century; +} + +uint8_t Time::get_millennium(void) +{ + return Time::get_date().millennia; +} + +const char* Time::get_day_string(void) +{ + return days[0]; //TODO +} + +const char* Time::get_day_string(int day) +{ + return days[day - 1]; +} + +const char* Time::get_month_string(void) +{ + return months[get_month() - 1]; +} + +const char* Time::get_month_string(int month) +{ + return months[month - 1]; +} + +const char* Time::get_weekday(void) +{ + timedate date = RTC::get_date(); + UNUSED_VARIABLE(date); + return days[0]; //TODO +} + +const char* Time::get_weekday(timedate date) +{ + UNUSED_VARIABLE(date); + return days[0]; //TODO +} + +const char* Time::get_date_formatted(void) +{ + //HH:MM:SS + static char buf[9]; //temp as we dont have mem alloc + itoa(get_hour(), buf, 2); + if(strlen(buf) == 1) + { + buf[1] = buf[0]; + buf[0] = '0'; + } + buf[2] = ':'; + itoa(get_minute(), buf + 3, 2); + if(strlen(buf) == 4) + { + buf[4] = buf[3]; + buf[3] = '0'; + } + buf[5] = ':'; + itoa(get_second(), buf + 6, 2); + if(strlen(buf) == 7) + { + buf[7] = buf[6]; + buf[6] = '0'; + } + + buf[8] = '\0'; + + return buf; +} diff --git a/src/pOS/arch/x86/kernel/tty.cpp b/src/pOS/arch/x86/kernel/tty.cpp new file mode 100644 index 0000000..daada0f --- /dev/null +++ b/src/pOS/arch/x86/kernel/tty.cpp @@ -0,0 +1,111 @@ +#include <kernel/tty.h> + +size_t TTY::tty_y; +size_t TTY::tty_x; +uint8_t TTY::tty_color; +uint16_t* TTY::tty_buf; +uint16_t TTY::tty_map[VGA::VGA::VGA_WIDTH][VGA::VGA::VGA_HEIGHT]; + +int TTY::tty_cursor_updt(void) +{ + uint16_t indx = tty_y * VGA::VGA::VGA_WIDTH + tty_x; + + System::outb(0x3D4, 14); + System::outb(0x3D5, indx >> 8); + System::outb(0x3D4, 15); + System::outb(0x3D5, indx); + + return 0; +} + +int TTY::tty_scroll(void) +{ + if(tty_y + 1 >= VGA::VGA::VGA_HEIGHT) + { + /* move everything up */ + for(size_t x = 0; x < VGA::VGA::VGA_WIDTH; x++) + for(size_t y = 0; y < VGA::VGA::VGA_HEIGHT - 1; y++) + tty_map[x][y] = tty_map[x][y + 1]; + + /* clear last line */ + for(size_t i = 0; i < VGA::VGA::VGA_WIDTH; i++) + tty_map[i][VGA::VGA::VGA_HEIGHT - 1] = VGA::vga_entry(' ', tty_color); + + tty_y--; + tty_update(); + } + + return 0; +} + +int TTY::tty_update(void) /* NOT EFFICIENT */ +{ + for (size_t x = 0; x < VGA::VGA::VGA_WIDTH; x++) + for (size_t y = 0; y < VGA::VGA::VGA_HEIGHT; y++) + tty_buf[y * VGA::VGA::VGA_WIDTH + x] = tty_map[x][y]; + + tty_cursor_updt(); + tty_scroll(); + + return 0; +} + +int TTY::tty_putentryat(unsigned char c, uint8_t color, size_t x, size_t y) +{ + tty_map[x][y] = VGA::vga_entry(c, color); + if(++tty_x >= VGA::VGA::VGA_WIDTH) + { + tty_x = tty_x - VGA::VGA::VGA_WIDTH; + tty_y++; + } + + tty_update(); + return 0; +} + +int TTY::tty_initialize(void) +{ + tty_y = 0; + tty_x = 0; + tty_color = VGA::vga_entry_color(VGA::VGA_COLOR_GREEN, VGA::VGA_COLOR_BLACK); + tty_buf = (uint16_t*)VGA::VGA_MEMORY; + for (size_t y = 0; y < VGA::VGA::VGA_HEIGHT; y++) + for (size_t x = 0; x < VGA::VGA::VGA_WIDTH; x++) + tty_map[x][y] = VGA::vga_entry(' ', tty_color); + + tty_update(); + + return 0; +} + +int TTY::tty_setcolor(uint8_t color) +{ + tty_color = color; + return 0; +} + +int TTY::tty_putc(char c) +{ + if(c == '\n') + { + tty_x = 0; + tty_y++; + return 0; + } + else if(c == '\t') + { + tty_x += 4; + return 0; + } //add \r + + tty_putentryat((unsigned char)c, tty_color, tty_x, tty_y); + + return 0; +} + +int TTY::tty_write(const char* data, size_t size) +{ + for (size_t i = 0; i < size; i++) + tty_putc(data[i]); + return 0; +} diff --git a/src/pOS/arch/x86/libc/math.c b/src/pOS/arch/x86/libc/math.c new file mode 100644 index 0000000..c83d132 --- /dev/null +++ b/src/pOS/arch/x86/libc/math.c @@ -0,0 +1,22 @@ +#include <math.h> + +int min(int a, int b) +{ + return (a < b) ? a : b; +} + +int max(int a, int b) +{ + return (a > b) ? a : b; +} + +int pow(int num, int p) +{ + int result = 1; + for(int i = 0; i < p; i++) + { + result *= num; + } + + return result; +} diff --git a/src/pOS/arch/x86/libc/stdio/printf.cpp b/src/pOS/arch/x86/libc/stdio/printf.cpp new file mode 100644 index 0000000..dc880ac --- /dev/null +++ b/src/pOS/arch/x86/libc/stdio/printf.cpp @@ -0,0 +1,37 @@ +#include <stdio.h> + +static bool serial_debug = false; + +void Debug::set_serial_debug(bool state) +{ + serial_debug = state; +} + +static void console_out(char c) +{ + if (serial_debug) + Serial::serial_putch(c); + + putc(c); +} + +static void console_putch(char*&, char c) //wrapper so that we can sprintf +{ + console_out(c); +} + +int printf(const char* fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + int result = printf_internal(console_putch, nullptr, fmt, ap); + va_end(ap); + return result; +} + +int print(const char* str, int len) +{ + for (int i = 0; i < len; ++i) + console_out(str[i]); + return 0; +} diff --git a/src/pOS/arch/x86/libc/stdio/putc.cpp b/src/pOS/arch/x86/libc/stdio/putc.cpp new file mode 100644 index 0000000..ce01839 --- /dev/null +++ b/src/pOS/arch/x86/libc/stdio/putc.cpp @@ -0,0 +1,6 @@ +#include <stdio.h> + +int putc(const char c) +{ + return TTY::tty_putc(c); +} diff --git a/src/pOS/arch/x86/libc/stdio/sprintf.cpp b/src/pOS/arch/x86/libc/stdio/sprintf.cpp new file mode 100644 index 0000000..e7df4d3 --- /dev/null +++ b/src/pOS/arch/x86/libc/stdio/sprintf.cpp @@ -0,0 +1,16 @@ +#include <stdio.h> + +static void buffer_putch(char*& bufptr, char c) +{ + *bufptr++ = c; +} + +int sprintf(char* buf, const char* fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + int result = printf_internal(buffer_putch, buf, fmt, ap); + buf[result] = '\0'; + va_end(ap); + return result; +} diff --git a/src/pOS/arch/x86/libc/stdlib/atoi.cpp b/src/pOS/arch/x86/libc/stdlib/atoi.cpp new file mode 100644 index 0000000..46b8d5f --- /dev/null +++ b/src/pOS/arch/x86/libc/stdlib/atoi.cpp @@ -0,0 +1,34 @@ +#include <stdlib.h> + +static int to_int(char c) +{ + return c - '0'; +} + +static bool is_num(char c) +{ + return (c >= '0' && c <= '9'); +} + +int atoi(const char* str) +{ + int result = 0; + int index = 0; + + if(str[0] == '-') + index++; + + while(str[index] != '\0') + { + ASSERT(is_num(str[index])); + result = (to_int(str[index]) + (10 * result)); + index++; + } + + if(str[0] == '-') + { + result *= -1; + } + + return result; +} diff --git a/src/pOS/arch/x86/libc/stdlib/itoa.cpp b/src/pOS/arch/x86/libc/stdlib/itoa.cpp new file mode 100644 index 0000000..722265d --- /dev/null +++ b/src/pOS/arch/x86/libc/stdlib/itoa.cpp @@ -0,0 +1,31 @@ +#include <stdlib.h> + +int itoa(int i, char* buf, size_t len) +{ + const char* digit = "0123456789"; + size_t index = 0; + + if(i < 0) + { + buf[index++] = '-'; + i *= -1; + } + + int shifter = i; + + do + { + index++; + shifter /= 10; + }while(len > index && shifter); + + buf[index] = '\0'; + + do + { + buf[--index] = digit[i % 10]; + i /= 10; + }while(i); + + return 0; +} diff --git a/src/pOS/arch/x86/libc/string/memcpy.cpp b/src/pOS/arch/x86/libc/string/memcpy.cpp new file mode 100644 index 0000000..2f5c978 --- /dev/null +++ b/src/pOS/arch/x86/libc/string/memcpy.cpp @@ -0,0 +1,10 @@ +#include <string.h> + +void* memcpy(void* dst, const void* src, size_t size) +{ + uint8_t* dstptr = static_cast<uint8_t*>(dst); + const uint8_t* srcptr = static_cast<const uint8_t*>(src); + for (size_t i = 0; i < size; i++) + dstptr[i] = srcptr[i]; + return dst; +} diff --git a/src/pOS/arch/x86/libc/string/memset.cpp b/src/pOS/arch/x86/libc/string/memset.cpp new file mode 100644 index 0000000..35ab14a --- /dev/null +++ b/src/pOS/arch/x86/libc/string/memset.cpp @@ -0,0 +1,11 @@ +#include <string.h> + +void* memset(void* buf, int value, size_t size) +{ + uint8_t* bufptr = static_cast<uint8_t*>(buf); + + for(size_t i = 0; i < size; i++) + *bufptr = (uint8_t)value; + + return buf; +} diff --git a/src/pOS/arch/x86/libc/string/strlen.cpp b/src/pOS/arch/x86/libc/string/strlen.cpp new file mode 100644 index 0000000..e28aed6 --- /dev/null +++ b/src/pOS/arch/x86/libc/string/strlen.cpp @@ -0,0 +1,9 @@ +#include <string.h> + +size_t strlen(const char* str) +{ + size_t len = 0; + while (str[len] != '\0') + len++; + return len; +} diff --git a/src/pOS/arch/x86/libc/string/strncpy.cpp b/src/pOS/arch/x86/libc/string/strncpy.cpp new file mode 100644 index 0000000..1881001 --- /dev/null +++ b/src/pOS/arch/x86/libc/string/strncpy.cpp @@ -0,0 +1,14 @@ +#include <string.h> + +char* strncpy(char* dst, const char* src, size_t len) +{ + if(!dst) + return NULL; + char* dstptr = dst; + + while(*src && len--) + *dst++ = *src++; + *dst = '\0'; + + return dstptr; +} diff --git a/src/pOS/include/kernel/debug.h b/src/pOS/include/kernel/debug.h new file mode 100644 index 0000000..61dddee --- /dev/null +++ b/src/pOS/include/kernel/debug.h @@ -0,0 +1,11 @@ +#ifndef _DEBUG_H_ +#define _DEBUG_H_ + +#include <stdarg.h> +#include <printf_internal.h> +#include <kernel/serial.h> + +int dbgprintf(const char* fmt, ...); +int dbgprint(const char* str, int len); + +#endif diff --git a/src/pOS/include/kernel/pOS.h b/src/pOS/include/kernel/pOS.h new file mode 100644 index 0000000..278b0a1 --- /dev/null +++ b/src/pOS/include/kernel/pOS.h @@ -0,0 +1,7 @@ +#ifndef _POS_H_ +#define _POS_H_ + +#define DEBUG +#define VERSION "meme" + +#endif diff --git a/src/pOS/include/kernel/rtc.h b/src/pOS/include/kernel/rtc.h new file mode 100644 index 0000000..c0aa71d --- /dev/null +++ b/src/pOS/include/kernel/rtc.h @@ -0,0 +1,30 @@ +#ifndef _RTC_H_ +#define _RTC_H_ + +#include <stdint.h> +#include <kernel/time.h> +#include <kernel/system.h> + +#define CMOS_PORT 0x70 +#define CMOS_DATA 0x71 + +#define CMOS_READ_SECOND 0x00 +#define CMOS_READ_MINUTE 0x02 +#define CMOS_READ_HOUR 0x04 +#define CMOS_READ_DAY 0x07 +#define CMOS_READ_MONTH 0x08 +#define CMOS_READ_YEAR 0x09 + +#define CURRENT_CENTURY 21 +#define CURRENT_MILLENNIUM 3 + +class RTC +{ +public: + static timedate get_date(void); +private: + static int get_update_in_progress_flag(void); + static uint8_t read_cmos(uint8_t registr); +}; + +#endif diff --git a/src/pOS/include/kernel/serial.h b/src/pOS/include/kernel/serial.h new file mode 100644 index 0000000..75746c3 --- /dev/null +++ b/src/pOS/include/kernel/serial.h @@ -0,0 +1,24 @@ +#ifndef _SERIAL_H_ +#define _SERIAL_H_ + +#include <kernel/system.h> + +#define COM1_PORT 0x3f8 +#define COM2_PORT 0x2f8 +#define COM3_PORT 0x3e8 +#define COM4_PORT 0x2e8 + +class Serial +{ +public: + static int init_serial(uint16_t port); + static int write_serial(uint8_t data, uint16_t port); + static uint8_t read_serial(uint16_t port); + static int serial_putch(char c); +private: + static int is_transmit_empty(uint16_t port); + static int serial_received(uint16_t port); + +}; + +#endif diff --git a/src/pOS/include/kernel/system.h b/src/pOS/include/kernel/system.h new file mode 100644 index 0000000..146ceed --- /dev/null +++ b/src/pOS/include/kernel/system.h @@ -0,0 +1,15 @@ +#ifndef _SYSTEM_H_ +#define _SYSTEM_H_ + +#include <stdint.h> + +class System +{ +public: + static uint8_t inb(uint16_t port); + static void outb(uint16_t port, uint8_t data); + + static int idle_loop(void); +}; + +#endif diff --git a/src/pOS/include/kernel/time.h b/src/pOS/include/kernel/time.h new file mode 100644 index 0000000..7038daf --- /dev/null +++ b/src/pOS/include/kernel/time.h @@ -0,0 +1,43 @@ +#ifndef _TIME_H_ +#define _TIME_H_ + +#include <stdint.h> +#include <stdlib.h> +#include <string.h> + +struct timedate +{ + uint8_t second; + uint8_t minute; + uint8_t hour; + uint8_t day; + uint8_t month; + uint8_t year; + uint8_t century; + uint8_t millennia; +}; + +#include <kernel/rtc.h> + +class Time +{ +public: + static timedate get_date(void); + static uint8_t get_second(void); + static uint8_t get_minute(void); + static uint8_t get_hour(void); + static uint8_t get_day(void); + static uint8_t get_month(void); + static uint8_t get_year(void); + static uint8_t get_century(void); + static uint8_t get_millennium(void); + static const char* get_day_string(void); + static const char* get_day_string(int day); + static const char* get_month_string(void); + static const char* get_month_string(int month); + static const char* get_weekday(void); + static const char* get_weekday(timedate date); + static const char* get_date_formatted(void); +}; + +#endif diff --git a/src/pOS/include/kernel/tty.h b/src/pOS/include/kernel/tty.h new file mode 100644 index 0000000..23b46dc --- /dev/null +++ b/src/pOS/include/kernel/tty.h @@ -0,0 +1,29 @@ +#ifndef _TTY_H_ +#define _TTY_H_ + +#include <string.h> +#include <kernel/vga.h> +#include <kernel/system.h> + +class TTY +{ +public: + static int tty_initialize(void); + static int tty_setcolor(uint8_t color); + static int tty_putc(char c); + static int tty_write(const char* data, size_t size); +private: + static int tty_putentryat(unsigned char c, uint8_t color, size_t x, size_t y); + static int tty_update(void); + static int tty_scroll(void); + static int tty_cursor_updt(void); + + static size_t tty_y; + static size_t tty_x; + static uint8_t tty_color; + static uint16_t* tty_buf; + static uint16_t tty_map[VGA::VGA_WIDTH][VGA::VGA_HEIGHT]; +}; + + +#endif diff --git a/src/pOS/include/kernel/vga.h b/src/pOS/include/kernel/vga.h new file mode 100644 index 0000000..ce21848 --- /dev/null +++ b/src/pOS/include/kernel/vga.h @@ -0,0 +1,44 @@ +#ifndef _VGA_H_ +#define _VGA_H_ + +#include <stdint.h> +#include <stddef.h> + +class VGA +{ +public: + static constexpr int VGA_WIDTH = 80; + static constexpr int VGA_HEIGHT = 25; + static constexpr uint16_t* VGA_MEMORY = reinterpret_cast<uint16_t*>(0xb8000); + + enum vga_colors { + VGA_COLOR_BLACK, + VGA_COLOR_BLUE, + VGA_COLOR_GREEN, + VGA_COLOR_CYAN, + VGA_COLOR_RED, + VGA_COLOR_MAGENTA, + VGA_COLOR_BROWN, + VGA_COLOR_LIGHT_GREY, + VGA_COLOR_DARK_GREY, + VGA_COLOR_LIGHT_BLUE, + VGA_COLOR_LIGHT_GREEN, + VGA_COLOR_LIGHT_CYAN, + VGA_COLOR_LIGHT_RED, + VGA_COLOR_LIGHT_MAGENTA, + VGA_COLOR_LIGHT_BROWN, + VGA_COLOR_WHITE, + }; + + static uint8_t vga_entry_color(enum vga_colors fg, enum vga_colors bg) + { + return fg | bg << 4; + } + + static uint16_t vga_entry(unsigned char uc, uint8_t color) + { + return (uint16_t) uc | (uint16_t) color << 8; + } +}; + +#endif diff --git a/src/pOS/include/libc/assert.h b/src/pOS/include/libc/assert.h new file mode 100644 index 0000000..3eae3c5 --- /dev/null +++ b/src/pOS/include/libc/assert.h @@ -0,0 +1,14 @@ +#ifndef _ASSERT_H_ +#define _ASSERT_H_ + +#include <stdio.h> + +#define ASSERT(EXPR) (void)((EXPR) || (_assert (#EXPR, __FILE__, __LINE__),0)) + +static inline void _assert(const char* expr, const char* file, int line) +{ + printf("Assertion failed! (%s) - %s:%d\n", expr, file ,line); + /* TODO: Implement exit */ +} + +#endif diff --git a/src/pOS/include/libc/math.h b/src/pOS/include/libc/math.h new file mode 100644 index 0000000..76953fb --- /dev/null +++ b/src/pOS/include/libc/math.h @@ -0,0 +1,8 @@ +#ifndef _MATH_H_ +#define _MATH_H_ + +int min(int a, int b); +int max(int a, int b); +int pow(int num, int p); + +#endif diff --git a/src/pOS/include/libc/printf_internal.h b/src/pOS/include/libc/printf_internal.h new file mode 100644 index 0000000..c2ae2fd --- /dev/null +++ b/src/pOS/include/libc/printf_internal.h @@ -0,0 +1,409 @@ +#ifndef _PRINTF_INTERNAL_H_ +#define _PRINTF_INTERNAL_H_ + +#include <stdarg.h> +#include <string.h> +#include <math.h> + +/* FROM SERENITYOS */ + +static constexpr const char* printf_hex_digits_lower = "0123456789abcdef"; +static constexpr const char* printf_hex_digits_upper = "0123456789ABCDEF"; + +template<typename PutChFunc, typename T> +inline int print_hex(PutChFunc putch, char*& bufptr, T number, bool upper_case, bool alternate_form, bool left_pad, bool zero_pad, uint8_t field_width) +{ + int ret = 0; + + int digits = 0; + for (T n = number; n > 0; n >>= 4) + ++digits; + if (digits == 0) + digits = 1; + + if (left_pad) { + int stop_at = field_width - digits; + if (alternate_form) + stop_at -= 2; + + while (ret < stop_at) { + putch(bufptr, ' '); + ++ret; + } + } + + if (alternate_form) { + putch(bufptr, '0'); + putch(bufptr, 'x'); + ret += 2; + field_width += 2; + } + + if (zero_pad) { + while (ret < field_width - digits) { + putch(bufptr, '0'); + ++ret; + } + } + + if (number == 0) { + putch(bufptr, '0'); + ++ret; + } else { + uint8_t shift_count = digits * 4; + while (shift_count) { + shift_count -= 4; + putch(bufptr, + upper_case + ? printf_hex_digits_upper[(number >> shift_count) & 0x0f] + : printf_hex_digits_lower[(number >> shift_count) & 0x0f]); + ++ret; + } + } + + return ret; +} + +template<typename PutChFunc> +inline int print_number(PutChFunc putch, char*& bufptr, uint32_t number, bool left_pad, bool zero_pad, uint32_t field_width) +{ + uint32_t divisor = 1000000000; + char ch; + char padding = 1; + char buf[16]; + char* p = buf; + + for (;;) { + ch = '0' + (number / divisor); + number %= divisor; + if (ch != '0') + padding = 0; + if (!padding || divisor == 1) + *(p++) = ch; + if (divisor == 1) + break; + divisor /= 10; + } + + size_t numlen = p - buf; + if (!field_width || field_width < numlen) + field_width = numlen; + if (!left_pad) { + for (unsigned i = 0; i < field_width - numlen; ++i) { + putch(bufptr, zero_pad ? '0' : ' '); + } + } + for (unsigned i = 0; i < numlen; ++i) { + putch(bufptr, buf[i]); + } + if (left_pad) { + for (unsigned i = 0; i < field_width - numlen; ++i) { + putch(bufptr, ' '); + } + } + + return field_width; +} + +template<typename PutChFunc> +inline int print_uint64_t(PutChFunc putch, char*& bufptr, uint64_t number, bool left_pad, bool zero_pad, uint32_t field_width) +{ + uint64_t divisor = 10000000000000000000LLU; + char ch; + char padding = 1; + char buf[16]; + char* p = buf; + + for (;;) { + ch = '0' + (number / divisor); + number %= divisor; + if (ch != '0') + padding = 0; + if (!padding || divisor == 1) + *(p++) = ch; + if (divisor == 1) + break; + divisor /= 10; + } + + size_t numlen = p - buf; + if (!field_width || field_width < numlen) + field_width = numlen; + if (!left_pad) { + for (unsigned i = 0; i < field_width - numlen; ++i) { + putch(bufptr, zero_pad ? '0' : ' '); + } + } + for (unsigned i = 0; i < numlen; ++i) { + putch(bufptr, buf[i]); + } + if (left_pad) { + for (unsigned i = 0; i < field_width - numlen; ++i) { + putch(bufptr, ' '); + } + } + + return field_width; +} + +template<typename PutChFunc> +inline int print_double(PutChFunc putch, char*& bufptr, double number, bool left_pad, bool zero_pad, uint32_t field_width, uint32_t fraction_length = 6) +{ + int length = 0; + + if (number < 0) { + putch(bufptr, '-'); + length++; + number = 0 - number; + } + + length = print_uint64_t(putch, bufptr, (int64_t)number, left_pad, zero_pad, field_width); + putch(bufptr, '.'); + length++; + double fraction = number - (int64_t)number; + + for (uint32_t i = 0; i < fraction_length; ++i) + fraction = fraction * 10; + + return length + print_uint64_t(putch, bufptr, (int64_t)fraction, false, true, fraction_length); +} + +template<typename PutChFunc> +inline int print_int64_t(PutChFunc putch, char*& bufptr, int64_t number, bool left_pad, bool zero_pad, uint32_t field_width) +{ + if (number < 0) { + putch(bufptr, '-'); + return print_uint64_t(putch, bufptr, 0 - number, left_pad, zero_pad, field_width) + 1; + } + return print_uint64_t(putch, bufptr, number, left_pad, zero_pad, field_width); +} + +template<typename PutChFunc> +inline int print_octal_number(PutChFunc putch, char*& bufptr, uint32_t number, bool left_pad, bool zero_pad, uint32_t field_width) +{ + uint32_t divisor = 134217728; + char ch; + char padding = 1; + char buf[32]; + char* p = buf; + + for (;;) { + ch = '0' + (number / divisor); + number %= divisor; + if (ch != '0') + padding = 0; + if (!padding || divisor == 1) + *(p++) = ch; + if (divisor == 1) + break; + divisor /= 8; + } + + size_t numlen = p - buf; + if (!field_width || field_width < numlen) + field_width = numlen; + if (!left_pad) { + for (unsigned i = 0; i < field_width - numlen; ++i) { + putch(bufptr, zero_pad ? '0' : ' '); + } + } + for (unsigned i = 0; i < numlen; ++i) { + putch(bufptr, buf[i]); + } + if (left_pad) { + for (unsigned i = 0; i < field_width - numlen; ++i) { + putch(bufptr, ' '); + } + } + + return field_width; +} + +template<typename PutChFunc> +inline int print_string(PutChFunc putch, char*& bufptr, const char* str, size_t len, bool left_pad, size_t field_width, bool dot) +{ + if (!dot && (!field_width || field_width < len)) + field_width = len; + size_t pad_amount = field_width > len ? field_width - len : 0; + + if (!left_pad) { + for (size_t i = 0; i < pad_amount; ++i) + putch(bufptr, ' '); + } + for (int i = 0; i < min(len, field_width); ++i) { + putch(bufptr, str[i]); + } + if (left_pad) { + for (size_t i = 0; i < pad_amount; ++i) + putch(bufptr, ' '); + } + return field_width; +} + +template<typename PutChFunc> +inline int print_signed_number(PutChFunc putch, char*& bufptr, int number, bool left_pad, bool zero_pad, uint32_t field_width, bool always_sign) +{ + if (number < 0) { + putch(bufptr, '-'); + return print_number(putch, bufptr, 0 - number, left_pad, zero_pad, field_width) + 1; + } + if (always_sign) + putch(bufptr, '+'); + return print_number(putch, bufptr, number, left_pad, zero_pad, field_width); +} + +template<typename PutChFunc> +inline int printf_internal(PutChFunc putch, char* buffer, const char*& fmt, va_list ap) +{ + const char* p; + + int ret = 0; + char* bufptr = buffer; + + for (p = fmt; *p; ++p) { + bool left_pad = false; + bool zero_pad = false; + bool dot = false; + unsigned field_width = 0; + unsigned fraction_length = 0; + unsigned long_qualifiers = 0; + bool size_qualifier = false; + (void)size_qualifier; + bool alternate_form = 0; + bool always_sign = false; + if (*p == '%' && *(p + 1)) { + one_more: + ++p; + if (*p == '.') { + dot = true; + if (*(p + 1)) + goto one_more; + } + if (*p == '-') { + left_pad = true; + if (*(p + 1)) + goto one_more; + } + if (*p == '+') { + always_sign = true; + if (*(p + 1)) + goto one_more; + } + if (!zero_pad && !field_width && *p == '0') { + zero_pad = true; + if (*(p + 1)) + goto one_more; + } + if (*p >= '0' && *p <= '9') { + if (!dot) { + field_width *= 10; + field_width += *p - '0'; + if (*(p + 1)) + goto one_more; + } else { + fraction_length *= 10; + fraction_length += *p - '0'; + if (*(p + 1)) + goto one_more; + } + } + if (*p == '*') { + field_width = va_arg(ap, int); + if (*(p + 1)) + goto one_more; + } + if (*p == 'l') { + ++long_qualifiers; + if (*(p + 1)) + goto one_more; + } + if (*p == 'z') { + size_qualifier = true; + if (*(p + 1)) + goto one_more; + } + if (*p == '#') { + alternate_form = true; + if (*(p + 1)) + goto one_more; + } + switch (*p) { + case 's': { + const char* sp = va_arg(ap, const char*); + if (!sp) + sp = "(null)"; + ret += print_string(putch, bufptr, sp, strlen(sp), left_pad, field_width, dot); + } break; + + case 'd': + case 'i': + if (long_qualifiers >= 2) + ret += print_int64_t(putch, bufptr, va_arg(ap, int64_t), left_pad, zero_pad, field_width); + else + ret += print_signed_number(putch, bufptr, va_arg(ap, int), left_pad, zero_pad, field_width, always_sign); + break; + + case 'u': + if (long_qualifiers >= 2) + ret += print_uint64_t(putch, bufptr, va_arg(ap, uint64_t), left_pad, zero_pad, field_width); + else + ret += print_number(putch, bufptr, va_arg(ap, uint32_t), left_pad, zero_pad, field_width); + break; + + case 'Q': + ret += print_uint64_t(putch, bufptr, va_arg(ap, uint64_t), left_pad, zero_pad, field_width); + break; + + case 'q': + ret += print_hex(putch, bufptr, va_arg(ap, uint64_t), false, false, left_pad, zero_pad, 16); + break; + + case 'o': + if (alternate_form) { + putch(bufptr, '0'); + ++ret; + } + ret += print_octal_number(putch, bufptr, va_arg(ap, uint32_t), left_pad, zero_pad, field_width); + break; + + case 'X': + case 'x': + ret += print_hex(putch, bufptr, va_arg(ap, uint32_t), *p == 'X', alternate_form, left_pad, zero_pad, field_width); + break; + + case 'w': + ret += print_hex(putch, bufptr, va_arg(ap, int), false, alternate_form, false, true, 4); + break; + + case 'b': + ret += print_hex(putch, bufptr, va_arg(ap, int), false, alternate_form, false, true, 2); + break; + + case 'c': { + char c = va_arg(ap, int); + ret += print_string(putch, bufptr, &c, 1, left_pad, field_width, dot); + } break; + + case '%': + putch(bufptr, '%'); + ++ret; + break; + + case 'P': + case 'p': + ret += print_hex(putch, bufptr, va_arg(ap, uint32_t), *p == 'P', true, false, true, 8); + break; + + case 'n': + *va_arg(ap, int*) = ret; + break; + } + } else { + putch(bufptr, *p); + ++ret; + } + } + return ret; +} + +#endif diff --git a/src/pOS/include/libc/stddef.h b/src/pOS/include/libc/stddef.h new file mode 100644 index 0000000..2f2cb80 --- /dev/null +++ b/src/pOS/include/libc/stddef.h @@ -0,0 +1,9 @@ +#ifndef _STDDEF_H_ +#define _STDDEF_H_ + +#define NULL 0 +#define UNUSED_VARIABLE(x) (void)x + +typedef unsigned long long size_t; + +#endif diff --git a/src/pOS/include/libc/stdint.h b/src/pOS/include/libc/stdint.h new file mode 100644 index 0000000..0ba184a --- /dev/null +++ b/src/pOS/include/libc/stdint.h @@ -0,0 +1,16 @@ +#ifndef _STDINT_H_ +#define _STDINT_H_ + +typedef signed char int8_t; +typedef unsigned char uint8_t; + +typedef signed short int16_t; +typedef unsigned short uint16_t; + +typedef signed long int32_t; +typedef unsigned long uint32_t; + +typedef signed long long int64_t; +typedef unsigned long long uint64_t; + +#endif diff --git a/src/pOS/include/libc/stdio.h b/src/pOS/include/libc/stdio.h new file mode 100644 index 0000000..844c817 --- /dev/null +++ b/src/pOS/include/libc/stdio.h @@ -0,0 +1,24 @@ +#ifndef _STDIO_H_ +#define _STDIO_H_ + +#include <stdarg.h> +#include <string.h> +#include <kernel/tty.h> +#include <printf_internal.h> +#include <kernel/serial.h> + +#define EOF (-1) + +int printf(const char* format, ...); +int sprintf(char* buf, const char* format, ...); +int print(const char* str); +int putc(const char c); + +class Debug +{ +public: + static void set_serial_debug(bool state); +}; + +#endif + diff --git a/src/pOS/include/libc/stdlib.h b/src/pOS/include/libc/stdlib.h new file mode 100644 index 0000000..d7e174e --- /dev/null +++ b/src/pOS/include/libc/stdlib.h @@ -0,0 +1,11 @@ +#ifndef _STDLIB_H_ +#define _STDLIB_H_ + +#include <stddef.h> +#include <stdbool.h> +#include <assert.h> + +int itoa(int i, char* buf, size_t len); +int atoi(const char* str); + +#endif diff --git a/src/pOS/include/libc/string.h b/src/pOS/include/libc/string.h new file mode 100644 index 0000000..6983641 --- /dev/null +++ b/src/pOS/include/libc/string.h @@ -0,0 +1,12 @@ +#ifndef _STRING_H_ +#define _STRING_H_ + +#include <stddef.h> +#include <stdint.h> + +size_t strlen(const char* str); +void* memset(void* buf, int value, size_t size); +void* memcpy(void* dst, const void* src, size_t size); +char* strncpy(char* dst, const char* src, size_t len); + +#endif diff --git a/src/pOS/kernel/kernel.cpp b/src/pOS/kernel/kernel.cpp new file mode 100644 index 0000000..9e2db30 --- /dev/null +++ b/src/pOS/kernel/kernel.cpp @@ -0,0 +1,25 @@ +#include <stdio.h> +#include <kernel/pOS.h> +#include <kernel/time.h> +#include <kernel/debug.h> +#include <math.h> +#include <assert.h> + +extern "C" int kmain(void) +{ + #ifdef DEBUG + Debug::set_serial_debug(true); + #endif + TTY::tty_initialize(); + + printf("Welcome to pOS v%s\n", VERSION); + dbgprintf("Hi host %d!\n", pow(3, 2)); + + printf("Current time: %s (%s-%d-%d%d)\n", Time::get_date_formatted(), Time::get_month_string(), Time::get_day(), Time::get_century() - 1, Time::get_year()); + + System::idle_loop(); + + ASSERT(false); + + return 1; +} |