diff --git a/Makefile b/Makefile index 7c981f8..bfb2ddf 100644 --- a/Makefile +++ b/Makefile @@ -33,14 +33,14 @@ mem: cp kernel/mem/*.o obj/ link: - $(LD) $(LFLAGS) -o isodir/boot/iceOS.bin obj/*.o + $(LD) $(LFLAGS) -o isodir/boot/vulcanos.bin obj/*.o iso: - grub-mkrescue isodir -o iceOS.iso + grub-mkrescue isodir -o vulcanos.iso clean: rm -rf obj/ kernel/*.o kernel/cpu/*.o - rm -rf kernel/shell/*.o kernel/mem/*.o + rm -rf kernel/userspace/*.o kernel/mem/*.o rm -rf kernel/drivers/*.o kernel/libc/*.o rm -rf iceOS.iso bochslog.txt commands isodir @@ -48,10 +48,10 @@ bochs: bochs -f bochs_cfg -q run: - qemu-system-x86_64 -cdrom iceOS.iso + qemu-system-x86_64 -cdrom vulcanos.iso -cpu qemu32 run-debug: - qemu-system-x86_64 -cdrom iceOS.iso -d exec,cpu + qemu-system-x86_64 -cdrom vulcanos.iso -d exec,cpu run-curses: - qemu-system-x86_64 -cdrom iceOS.iso -curses + qemu-system-x86_64 -cdrom vulcanos.iso -curses diff --git a/README.md b/README.md index d5aa61c..0b7d1d7 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,10 @@ # VulcanOS [![Build Status](https://travis-ci.com/ice-bit/vulcanos.svg?branch=master)](https://travis-ci.com/ice-bit/vulcanos) **VulcanOS** is a x86 monolithic kernel written in C from scratch following the UNIX philosophy. This project is just a student learning tool to know more about operating systems, do not expect nothing more than a toy. - +
+ +
VulcanOS running under QEMU
+


## Installation ### Requirements @@ -18,7 +21,7 @@ After that, you can build iceOS just by running the command listed below. 2. Type `make run` to start it in QEMU or `make bochs` to start it with bochs(only for debug purposes). You can also find a ISO file -[here](https://github.com/ice-bit/vulcanos/raw/master/imgs/vulcanos.iso)(md5sum: `5a969460e63eb5c4dcfa943dc2a3f39f`) +[here](https://github.com/ice-bit/vulcanos/raw/master/imgs/vulcanos.iso)(md5sum: `a706cdfeea573e08550e599717d3f519`) ## Features iceOS has the following features: diff --git a/grub.cfg b/grub.cfg index 38bd850..86afc3c 100644 --- a/grub.cfg +++ b/grub.cfg @@ -1,7 +1,7 @@ set timeout = 0 set default = 0 -menuentry "iceOS" { - multiboot2 /boot/iceOS.bin +menuentry "VulcanOS" { + multiboot2 /boot/vulcanos.bin boot -} \ No newline at end of file +} diff --git a/imgs/screenshot.png b/imgs/screenshot.png index cee5e04..6c367b3 100644 Binary files a/imgs/screenshot.png and b/imgs/screenshot.png differ diff --git a/imgs/iceOS.iso b/imgs/vulcanos.iso similarity index 98% rename from imgs/iceOS.iso rename to imgs/vulcanos.iso index 073eeae..b503130 100644 Binary files a/imgs/iceOS.iso and b/imgs/vulcanos.iso differ diff --git a/kernel/drivers/Makefile b/kernel/drivers/Makefile index 622502f..24cd3ff 100644 --- a/kernel/drivers/Makefile +++ b/kernel/drivers/Makefile @@ -1,11 +1,11 @@ OBJS = tty.o gdt.o idt.o isr.o timer.o keyboard.o \ - fs.o + fs.o cpuid.o CC = i686-elf-gcc # cross-compiler -CFLAGS = -m32 -fno-stack-protector -ffreestanding -Wall -Wextra -Werror -g -c +CFLAGS = -m32 -fno-stack-protector -DDEFAULT_USER=root -DDEFAULT_HOSTNAME=vulcan -ffreestanding -Wall -Wextra -Werror -g -c all:${OBJS} %.o: %.c - $(CC) $(CFLAGS) $< -o $@ \ No newline at end of file + $(CC) $(CFLAGS) $< -o $@ diff --git a/kernel/drivers/cpuid.c b/kernel/drivers/cpuid.c new file mode 100644 index 0000000..921ccab --- /dev/null +++ b/kernel/drivers/cpuid.c @@ -0,0 +1,195 @@ +#include "cpuid.h" +#include "../libc/string.h" +#define INTEL_MAGIC_NUMBER 0x756e6547 +#define AMD_MAGIC_NUMBER 0x68747541 +#define UNRECOGNIZED_CPU 0xBADFF + +static cpuid_t get_cpuid(icpuid_t cpu); +static icpuid_t detect_cpu(void); +static icpuid_t intel_cpu(void); +static icpuid_t amd_cpu(void); +static icpuid_t generic_cpu(void); + +icpuid_t detect_cpu(void) { + uint32_t ebx, null; + icpuid_t i_cpu; + + cpuid(0, null, ebx, null, null); + + // Select CPU brand + switch(ebx) { + case INTEL_MAGIC_NUMBER: + i_cpu = intel_cpu(); + break; + case AMD_MAGIC_NUMBER: + i_cpu = amd_cpu(); + break; + default: + i_cpu = generic_cpu(); + break; + } + + return i_cpu; +} + +icpuid_t intel_cpu(void) { + uint32_t eax, ebx, null; + icpuid_t icpu; + + // Fill the structure + cpuid(1, eax, ebx, null, null); + icpu.model = (eax >> 4) & 0xF; + icpu.family = (eax >> 8) & 0xF; + icpu.type = (eax >> 12) & 0xF; + icpu.brand = INTEL_MAGIC_NUMBER; + icpu.stepping = eax & 0xF; + icpu.reserved = eax >> 14; + + return icpu; +} + +icpuid_t amd_cpu(void) { + uint32_t eax, null; + icpuid_t icpu; + + // Fill the structure + cpuid(1, eax, null, null, null); + icpu.model = (eax >> 4) & 0xF; + icpu.family = (eax >> 8) & 0xF; + icpu.stepping = eax & 0xF; + icpu.reserved = eax >> 12; + icpu.brand = AMD_MAGIC_NUMBER; + + return icpu; +} + +icpuid_t generic_cpu(void) { + icpuid_t icpu; + + icpu.brand = UNRECOGNIZED_CPU; // Magic number for unknown CPUs + + return icpu; +} + +cpuid_t get_cpuid(icpuid_t cpu) { + cpuid_t cpuid; + uint8_t model[64]; + + // Recognize CPU brand + if(cpu.brand == AMD_MAGIC_NUMBER) { + switch(cpu.family) { + case 4: + strcpy(model, (uint8_t*)"486 model "); // Set model name + strcat(model, (void*)cpu.model); // Set model version + cpuid.model = model; + break; + case 5: + switch(cpu.model) { + case 0: + case 1: + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + strcpy(model, (uint8_t*)"K6 model "); // Set model name + strcat(model, (void*)cpu.model); // Set model version + cpuid.model = model; + break; + case 8: + strcpy(model, (uint8_t*)"K6-2 model "); // Set model name + strcat(model, (void*)cpu.model); // Set model version + cpuid.model = model; + break; + case 9: + strcpy(model, (uint8_t*)"K6-III model "); // Set model name + strcat(model, (void*)cpu.model); // Set model version + cpuid.model = model; + break; + default: + strcpy(model, (uint8_t*)"K5/K6 model "); // Set model name + strcat(model, (void*)cpu.model); // Set model version + cpuid.model = model; + break; + } + break; + case 6: + switch(cpu.model) { + case 1: + case 2: + case 3: + cpuid.model = (uint8_t*)"Duron model 3"; + break; + case 4: + strcpy(model, (uint8_t*)"Athlon model "); + strcat(model, (void*)cpu.model); + cpuid.model = model; + break; + case 6: + cpuid.model = (uint8_t*)"Athlon MP/Mobile Athlon Model 6"; + break; + case 7: + cpuid.model = (uint8_t*)"Mobile Duron Model 7"; + break; + default: + strcpy(model, (uint8_t*)"Duron/Athlon model "); + strcat(model, (void*)cpu.model); + cpuid.model = model; + break; + } + break; + } + } else if(cpu.brand == INTEL_MAGIC_NUMBER) { + switch(cpu.type) { + case 0: + cpuid.type =(uint8_t*)"Original OEM"; + break; + case 1: + cpuid.type = (uint8_t*)"Overdrive"; + break; + case 2: + cpuid.type = (uint8_t*)"Dual-capable"; + break; + case 3: + cpuid.type = (uint8_t*)"Reserved"; + break; + } + + switch(cpu.family) { + case 3: + cpuid.family = (uint8_t*)"i386"; + break; + case 4: + cpuid.family = (uint8_t*)"i486"; + break; + case 5: + cpuid.family = (uint8_t*)"Pentium II Model 5/Xeon/Celeron"; + break; + case 6: + cpuid.family = (uint8_t*)"Pentium Pro"; + break; + case 15: + cpuid.family = (uint8_t*)"Pentium 4"; + break; + } + } else if(cpu.brand == UNRECOGNIZED_CPU) + cpuid.family = (uint8_t*)"Generic (x86) CPU"; + + return cpuid; +} + +uint8_t *get_cpu_type() { + icpuid_t icpu = detect_cpu(); // Detect CPU brand(Intel, AMD or generic x86) + cpuid_t cpu_type = get_cpuid(icpu); + + return (uint8_t*)cpu_type.type; +} + +uint8_t *get_cpu_family() { + icpuid_t icpu = detect_cpu(); // Detect CPU brand(Intel, AMD or generic x86) + cpuid_t cpu_family = get_cpuid(icpu); + + return (uint8_t*)cpu_family.family; + +} diff --git a/kernel/drivers/cpuid.h b/kernel/drivers/cpuid.h new file mode 100644 index 0000000..ab11068 --- /dev/null +++ b/kernel/drivers/cpuid.h @@ -0,0 +1,36 @@ +/************************************** + * VulcanOS Kernel * + * Developed by Marco 'icebit' Cetica * + * (c) 2019-2021 * + * Released under GPLv3 * + * https://github.com/ice-bit/iceOS * + ***************************************/ +#ifndef CPUID_H +#define CPUID_H + +#include +#define cpuid(in, a, b, c, d) __asm__("cpuid": "=a" (a), "=b"(b), "=d" (d) : "a" (in)); + +typedef struct { + uint32_t model; + uint32_t family; + uint32_t type; + uint32_t brand; + uint32_t stepping; + uint32_t reserved; +} icpuid_t; + +typedef struct { + uint8_t *model; + uint8_t *family; + uint8_t *type; + uint8_t *brand; + uint8_t *stepping; + uint8_t *reserved; +} cpuid_t; + +// return type and family processor +uint8_t *get_cpu_type(); +uint8_t *get_cpu_family(); + +#endif diff --git a/kernel/drivers/tty.c b/kernel/drivers/tty.c index f95fce1..b24b7af 100644 --- a/kernel/drivers/tty.c +++ b/kernel/drivers/tty.c @@ -5,6 +5,8 @@ #define VGA_PTR ((uint8_t*) VIDEO_MEM_ADDR) // Pointer to frame buffer // Also define a 2 byte pointer because cells are 16 bits wide #define UVGA_PTR ((uint16_t *)VIDEO_MEM_ADDR) +#define STRINGIZE(x) #x +#define STRINGIZE_VALUE_OF(x) STRINGIZE(x) static uint32_t fb_col = 1; // X static uint32_t fb_row = 0; // Y @@ -95,8 +97,24 @@ void kprint_dec(uint32_t num) { } void init_prompt() { - uint8_t *prompt = (uint8_t*)"\nring0@iceOS-$ "; - kprint_c(prompt, strlen(prompt), LIGHT_RED, BLACK); + uint8_t user[64], hostname[64]; +#ifdef DEFAULT_USER + strcpy(user, (uint8_t*)STRINGIZE_VALUE_OF(DEFAULT_USER)); +#else + #error "-DDEFAULT_USER flag not set" +#endif + +#ifdef DEFAULT_HOSTNAME + strcpy(hostname, (uint8_t*)STRINGIZE_VALUE_OF(DEFAULT_HOSTNAME)); +#else + #error "-DDEFAULT_HOSTNAME flag not set" +#endif + + newline(); + kprint_c(user, strlen(user), LIGHT_GREEN, BLACK); + kprint_c((uint8_t*)"@", 1, BROWN, BLACK); + kprint_c(hostname, strlen(hostname), CYAN, BLACK); + kprint_c((uint8_t*)" #> ", 4, LIGHT_BROWN, BLACK); } void clear_prompt() { diff --git a/kernel/drivers/tty.h b/kernel/drivers/tty.h index 5bc294e..9aec33a 100644 --- a/kernel/drivers/tty.h +++ b/kernel/drivers/tty.h @@ -46,7 +46,6 @@ enum TTY_COLORS { #define VGA_LOW_BYTE 15 /* Kernel's VGA API */ -// FIXME: Set these functions to static void write_cell(int16_t i, uint8_t c, uint8_t fg, uint8_t bg); void move_cursor(uint16_t pos); void cursor_adv(); diff --git a/kernel/libc/string.c b/kernel/libc/string.c index 959edcd..0a30117 100644 --- a/kernel/libc/string.c +++ b/kernel/libc/string.c @@ -82,7 +82,7 @@ uint8_t *uitoa(uint32_t val, uint8_t *buf, uint32_t radix) { } size_t strlen(const uint8_t *buf) { - unsigned int i = 0; + uint32_t i = 0; while(buf[i] != 0) i++; return i; @@ -95,6 +95,13 @@ uint8_t *strcpy(uint8_t *dst, const uint8_t *src) { return dst_p; } +void strcat(void *dest, const void *src) { + uint8_t *end = (uint8_t*)dest + strlen(dest); + memcpy((uint8_t*)end, (uint8_t*)src, strlen((uint8_t*)src)); + end += strlen((uint8_t*)src); + *end = '\0'; +} + /* Worst memset implementation * i could find on the net. * however it works so... */ @@ -107,6 +114,17 @@ void *memset(void *s, uint32_t c, size_t n) { return s; } +void *memcpy(void *dst, void const *src, uint32_t n) { + uint8_t *ret = dst; + uint8_t *p = dst; + const uint8_t *q = src; + + while(n--) + *p++ = *q++; + + return ret; +} + void *memmove(void *dst, const void *src, size_t len) { char *dstmem = (char*)dst; char *srcmem = (char*)src; diff --git a/kernel/libc/string.h b/kernel/libc/string.h index ab341d7..fc50891 100644 --- a/kernel/libc/string.h +++ b/kernel/libc/string.h @@ -16,8 +16,10 @@ uint8_t *itoa(int32_t val, uint8_t *buf, uint32_t radix); uint8_t *uitoa(uint32_t val, uint8_t *buf, uint32_t radix); size_t strlen(const uint8_t *buf); uint8_t *strcpy(uint8_t *dst, const uint8_t *src); +void strcat(void *dest, const void *src); void *memset(void *s, uint32_t c, size_t n); void *memmove(void *dst, const void *src, size_t len); +void *memcpy(void *dst, void const *src, uint32_t n); void strupper(uint8_t *str); void strlower(uint8_t *str); diff --git a/kernel/userspace/Makefile b/kernel/userspace/Makefile index ac1b288..bf4f717 100644 --- a/kernel/userspace/Makefile +++ b/kernel/userspace/Makefile @@ -1,10 +1,10 @@ OBJS = shell.o fetch.o +VER := $(shell git rev-parse --short HEAD) CC = i686-elf-gcc # cross-compiler -CFLAGS = -DDEFAULT_USER=root -DDEFAULT_HOSTNAME=vulcan -m32 -fno-stack-protector -ffreestanding -Wall -Wextra -Werror -g -c +CFLAGS = -DDEFAULT_USER=root -DDEFAULT_HOSTNAME=vulcan -DVULCAN_VERSION=$(VER) -m32 -fno-stack-protector -ffreestanding -Wall -Wextra -Werror -g -c - -all:${OBJS} +all:${OBJS} %.o: %.c $(CC) $(CFLAGS) $< -o $@ diff --git a/kernel/userspace/fetch.c b/kernel/userspace/fetch.c index 95532ba..e461b6b 100644 --- a/kernel/userspace/fetch.c +++ b/kernel/userspace/fetch.c @@ -3,19 +3,16 @@ #include "../libc/string.h" #include "../libc/time.h" #include "../drivers/tty.h" - - - -void system_fetcher() { - /*uint8_t *logo = (uint8_t*)" \n \ - __ __ ___ ___ \n \ - \\ \\ / / / _ \\/ __| \n \ - \\ V / | (_) \\__ \\ \n \ - \\_/ \\___/|___/";*/ - - uint8_t user[64], hostname[64]; +#include "../drivers/cpuid.h" #define STRINGIZE(x) #x #define STRINGIZE_VALUE_OF(x) STRINGIZE(x) + +static void get_date(); +static void get_cpuid(); +static void get_version(); + +void system_fetcher() { + uint8_t user[64], hostname[64]; #ifdef DEFAULT_USER strcpy(user, (uint8_t*)STRINGIZE_VALUE_OF(DEFAULT_USER)); #else @@ -27,8 +24,52 @@ void system_fetcher() { #else #error "-DDEFAULT_HOSTNAME flag not set" #endif - printf_color("\n__ __ ___ ___ ", LIGHT_RED, BLACK); + // print first line + printf_color("\n __ __ ___ ___ ", LIGHT_RED, BLACK); printf_color((char*)user, LIGHT_CYAN, BLACK); printf_color("@", LIGHT_RED, BLACK); printf_color((char*)hostname, LIGHT_CYAN, BLACK); + // print second line + printf_color("\n \\ \\ / / / _ \\/ __| ", LIGHT_RED, BLACK); + printf_color("-----------", LIGHT_RED, BLACK); + // print third line + printf_color("\n \\ V / | (_) \\__ \\ ", LIGHT_RED, BLACK); + printf_color("Date: ", LIGHT_CYAN, BLACK); + get_date(); + // print fourth line + printf_color("\n \\_/ \\___/|___/ ", LIGHT_RED, BLACK); + get_cpuid(); + // print VulcanOS version + get_version(); +} + +// Date format is D/M/YY +void get_date() { + printf("%d", get_time(TIME_R_DAY)); // Day + printf_color("/", LIGHT_BLUE, BLACK); + + printf("%d", get_time(TIME_R_MONTH)); // Month + printf_color("/", LIGHT_BLUE, BLACK); + + printf("%d", get_time(TIME_R_YEAR)); // Year +} + + +void get_cpuid() { + printf_color("CPU type: ", LIGHT_CYAN, BLACK); + printf("%s", (char*)get_cpu_type()); // Print CPU type + printf("%s%s%c", " (", (char*)get_cpu_family(), ')'); +} + + +void get_version() { + uint8_t version[64]; +#ifdef VULCAN_VERSION + strcpy(version, (uint8_t*)STRINGIZE_VALUE_OF(VULCAN_VERSION)); +#else + #error "-DVULCAN_VERSION flag not set" +#endif + + printf_color("\n\t\t\t\t\t Version: ", LIGHT_CYAN, BLACK); + printf_color((char*)version, LIGHT_GREEN, BLACK); } diff --git a/kernel/userspace/shell.c b/kernel/userspace/shell.c index 467a2b1..73cde48 100644 --- a/kernel/userspace/shell.c +++ b/kernel/userspace/shell.c @@ -115,6 +115,8 @@ void processCommand(uint8_t *cmd) { system_fetcher(); else if(strcmp(cmd, (uint8_t*)"reboot") == 0) reboot(); + else if(strcmp(cmd, (uint8_t*)"") == 0) + puts(""); else puts("\nCommand not found!"); }