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!");
}