Refactoring assembly entry point

This commit is contained in:
Marco Cetica 2021-02-03 15:59:42 +01:00
parent dc3803491e
commit 1b207add8c
61 changed files with 4782 additions and 4779 deletions

106
.gitignore vendored
View File

@ -1,54 +1,54 @@
# Prerequisites # Prerequisites
*.d *.d
# Object files # Object files
*.o *.o
*.ko *.ko
*.obj *.obj
*.elf *.elf
# Linker output # Linker output
*.ilk *.ilk
*.map *.map
*.exp *.exp
# Precompiled Headers # Precompiled Headers
*.gch *.gch
*.pch *.pch
# Libraries # Libraries
*.lib *.lib
*.a *.a
*.la *.la
*.lo *.lo
# Shared objects (inc. Windows DLLs) # Shared objects (inc. Windows DLLs)
*.dll *.dll
*.so *.so
*.so.* *.so.*
*.dylib *.dylib
# Executables # Executables
*.exe *.exe
*.out *.out
*.app *.app
*.i*86 *.i*86
*.x86_64 *.x86_64
*.hex *.hex
# Debug files # Debug files
*.dSYM/ *.dSYM/
*.su *.su
*.idb *.idb
*.pdb *.pdb
# Kernel Module Compile Results # Kernel Module Compile Results
*.mod* *.mod*
*.cmd *.cmd
.tmp_versions/ .tmp_versions/
modules.order modules.order
Module.symvers Module.symvers
Mkfile.old Mkfile.old
dkms.conf dkms.conf
.vscode/* .vscode/*
TODO.md TODO.md

View File

@ -1,9 +1,9 @@
language: C language: C
before_install: before_install:
- sudo apt-get update - sudo apt-get update
- sudo apt-get install -y nasm grub-pc-bin - sudo apt-get install -y nasm grub-pc-bin
- sudo ln -s /usr/bin/gcc /usr/bin/i686-elf-gcc - sudo ln -s /usr/bin/gcc /usr/bin/i686-elf-gcc
- sudo ln -s /usr/bin/ld /usr/bin/i686-elf-ld - sudo ln -s /usr/bin/ld /usr/bin/i686-elf-ld
script: make clean all script: make clean all

1348
LICENSE

File diff suppressed because it is too large Load Diff

114
Makefile
View File

@ -1,57 +1,57 @@
LD = i686-elf-ld LD = i686-elf-ld
LFLAGS = -melf_i386 -nostdlib -O2 -T link.ld LFLAGS = -melf_i386 -nostdlib -O2 -T link.ld
all: prepare cpu kernel_code drivers libc userspace mem link iso all: prepare cpu kernel_code drivers libc userspace mem link iso
prepare: prepare:
mkdir -p obj/ mkdir -p obj/
mkdir -p isodir/boot/grub/ mkdir -p isodir/boot/grub/
cp grub.cfg isodir/boot/grub/grub.cfg cp grub.cfg isodir/boot/grub/grub.cfg
cpu: cpu:
make -C kernel/cpu make -C kernel/cpu
cp kernel/cpu/*.o obj/ cp kernel/cpu/*.o obj/
kernel_code: kernel_code:
make -C kernel make -C kernel
cp kernel/*.o obj/ cp kernel/*.o obj/
drivers: drivers:
make -C kernel/drivers/ make -C kernel/drivers/
cp kernel/drivers/*.o obj/ cp kernel/drivers/*.o obj/
libc: libc:
make -C kernel/libc make -C kernel/libc
cp kernel/libc/*.o obj/ cp kernel/libc/*.o obj/
userspace: userspace:
make -C kernel/userspace make -C kernel/userspace
cp kernel/userspace/*.o obj/ cp kernel/userspace/*.o obj/
mem: mem:
make -C kernel/mem make -C kernel/mem
cp kernel/mem/*.o obj/ cp kernel/mem/*.o obj/
link: link:
$(LD) $(LFLAGS) -o isodir/boot/vulcanos.bin obj/*.o $(LD) $(LFLAGS) -o isodir/boot/vulcanos.bin obj/*.o
iso: iso:
grub-mkrescue isodir -o vulcanos.iso grub-mkrescue isodir -o vulcanos.iso
clean: clean:
rm -rf obj/ kernel/*.o kernel/cpu/*.o rm -rf obj/ kernel/*.o kernel/cpu/*.o
rm -rf kernel/userspace/*.o kernel/mem/*.o rm -rf kernel/userspace/*.o kernel/mem/*.o
rm -rf kernel/drivers/*.o kernel/libc/*.o rm -rf kernel/drivers/*.o kernel/libc/*.o
rm -rf vulcanos.iso bochslog.txt commands isodir rm -rf vulcanos.iso bochslog.txt commands isodir
bochs: bochs:
bochs -f bochs_cfg -q bochs -f bochs_cfg -q
run: run:
qemu-system-x86_64 -cdrom vulcanos.iso -cpu qemu32 qemu-system-x86_64 -cdrom vulcanos.iso -cpu qemu32
run-debug: run-debug:
qemu-system-x86_64 -cdrom vulcanos.iso -d exec,cpu qemu-system-x86_64 -cdrom vulcanos.iso -d exec,cpu
run-curses: run-curses:
qemu-system-x86_64 -cdrom vulcanos.iso -curses -cpu qemu32 qemu-system-x86_64 -cdrom vulcanos.iso -curses -cpu qemu32

View File

@ -1,37 +1,37 @@
# VulcanOS [![Build Status](https://travis-ci.com/ice-bit/vulcanos.svg?branch=master)](https://travis-ci.com/ice-bit/vulcanos) # 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** 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.
<div align="center"> <div align="center">
<img src="imgs/screenshot.png" /> <img src="imgs/screenshot.png" />
<h6><i>VulcanOS running under QEMU</h6></i> <h6><i>VulcanOS running under QEMU</h6></i>
</div><br /><br /> </div><br /><br />
## Installation ## Installation
### Requirements ### Requirements
Before building this project you need to setup a [cross compiler](https://wiki.osdev.org/GCC_Cross-Compiler). Also install the following packages: Before building this project you need to setup a [cross compiler](https://wiki.osdev.org/GCC_Cross-Compiler). Also install the following packages:
- nasm - nasm
- bochs - bochs
- grub - grub
- mtools(only for Arch Linux) - mtools(only for Arch Linux)
After that, you can build iceOS just by running the command listed below. After that, you can build iceOS just by running the command listed below.
1. Type `make all` to compile the system and to create an ISO 1. Type `make all` to compile the system and to create an ISO
2. Type `make run` to start it in QEMU or `make bochs` to start it with bochs(only for debug purposes). 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 You can also find a ISO file
[here](https://github.com/ice-bit/vulcanos/raw/master/imgs/vulcanos.iso)(md5sum: `a706cdfeea573e08550e599717d3f519`) [here](https://github.com/ice-bit/vulcanos/raw/master/imgs/vulcanos.iso)(md5sum: `a706cdfeea573e08550e599717d3f519`)
## Features ## Features
iceOS has the following features: iceOS has the following features:
- [x] VGA driver - [x] VGA driver
- [x] Interrupts - [x] Interrupts
- [x] PIC & PIT driver - [x] PIC & PIT driver
- [x] PS/2 driver - [x] PS/2 driver
- [x] Heap - [x] Heap
- [x] Paging - [x] Paging
- [ ] VFS driver - [ ] VFS driver
- [ ] Usermode - [ ] Usermode
## License ## License
VulcanOS is released under GPLv3, you can obtain a copy of this license by cloning this repository or by visiting [this](https://opensource.org/licenses/GPL-3.0) page. VulcanOS is released under GPLv3, you can obtain a copy of this license by cloning this repository or by visiting [this](https://opensource.org/licenses/GPL-3.0) page.

View File

@ -1,12 +1,12 @@
# System configuration. # System configuration.
romimage: file=$BXSHARE/BIOS-bochs-latest romimage: file=$BXSHARE/BIOS-bochs-latest
vgaromimage: file=$BXSHARE/VGABIOS-lgpl-latest vgaromimage: file=$BXSHARE/VGABIOS-lgpl-latest
cpu: model=corei7_ivy_bridge_3770k, ips=120000000 cpu: model=corei7_ivy_bridge_3770k, ips=120000000
clock: sync=slowdown clock: sync=slowdown
megs: 256 megs: 256
boot: cdrom, disk boot: cdrom, disk
# CDROM # CDROM
ata1: enabled=1, ioaddr1=0x170, ioaddr2=0x370, irq=15 ata1: enabled=1, ioaddr1=0x170, ioaddr2=0x370, irq=15
ata1-master: type=cdrom, path="iceOS.iso", status=inserted ata1-master: type=cdrom, path="iceOS.iso", status=inserted

View File

@ -1,55 +1,55 @@
/* This program comes from James Molloy tutorial /* This program comes from James Molloy tutorial
* on how to create an UNIX clone You can find the original code at: * on how to create an UNIX clone You can find the original code at:
* http://www.jamesmolloy.co.uk/tutorial_html/8.-The%20VFS%20and%20the%20initrd.html */ * http://www.jamesmolloy.co.uk/tutorial_html/8.-The%20VFS%20and%20the%20initrd.html */
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
struct initrd_header { struct initrd_header {
unsigned char magic; // Magic number for consistency unsigned char magic; // Magic number for consistency
char name[64]; char name[64];
unsigned int offset; // Offset of the file start unsigned int offset; // Offset of the file start
unsigned int length; unsigned int length;
}; };
int main(int argc, char **argv) { int main(int argc, char **argv) {
int heads = (argc - 1) / 2; int heads = (argc - 1) / 2;
struct initrd_header headers[64]; struct initrd_header headers[64];
printf("Size of header(in bytes): %ld\n", sizeof(struct initrd_header)); printf("Size of header(in bytes): %ld\n", sizeof(struct initrd_header));
unsigned int off = sizeof(struct initrd_header) * 64 + sizeof(int); unsigned int off = sizeof(struct initrd_header) * 64 + sizeof(int);
for(int i = 0; i < heads; i++) { for(int i = 0; i < heads; i++) {
printf("Writing file %s->%s at 0x%d\n", argv[i*2+1], argv[i*2+2], off); printf("Writing file %s->%s at 0x%d\n", argv[i*2+1], argv[i*2+2], off);
strcpy(headers[i].name, argv[i*2+2]); strcpy(headers[i].name, argv[i*2+2]);
headers[i].offset = off; headers[i].offset = off;
FILE *stream = fopen(argv[i*2+1], "r"); FILE *stream = fopen(argv[i*2+1], "r");
if(stream == 0) { if(stream == 0) {
puts("Error, file not found!"); puts("Error, file not found!");
return 1; return 1;
} }
fseek(stream, 0, SEEK_END); fseek(stream, 0, SEEK_END);
headers[i].length = ftell(stream); headers[i].length = ftell(stream);
off += headers[i].length; off += headers[i].length;
fclose(stream); fclose(stream);
headers[i].magic = 0xBF; headers[i].magic = 0xBF;
} }
FILE *wstream = fopen("./initrd.img", "w"); FILE *wstream = fopen("./initrd.img", "w");
unsigned char *data = (unsigned char*)malloc(off); unsigned char *data = (unsigned char*)malloc(off);
fwrite(&heads, sizeof(int), 1, wstream); fwrite(&heads, sizeof(int), 1, wstream);
fwrite(&heads, sizeof(struct initrd_header), 64, wstream); fwrite(&heads, sizeof(struct initrd_header), 64, wstream);
for(int i = 0; i < heads; i++) { for(int i = 0; i < heads; i++) {
FILE *stream = fopen(argv[i*2+1], "r"); FILE *stream = fopen(argv[i*2+1], "r");
unsigned char *buf = (unsigned char*)malloc(headers[i].length); unsigned char *buf = (unsigned char*)malloc(headers[i].length);
fread(buf, 1, headers[i].length, stream); fread(buf, 1, headers[i].length, stream);
fread(buf, 1, headers[i].length, wstream); fread(buf, 1, headers[i].length, wstream);
fclose(stream); fclose(stream);
free(buf); free(buf);
} }
fclose(wstream); fclose(wstream);
free(data); free(data);
return 0; return 0;
} }

View File

@ -1,7 +1,7 @@
set timeout = 0 set timeout = 0
set default = 0 set default = 0
menuentry "VulcanOS" { menuentry "VulcanOS" {
multiboot2 /boot/vulcanos.bin multiboot2 /boot/vulcanos.bin
boot boot
} }

View File

@ -1,10 +1,10 @@
OBJS = kernel_main.o OBJS = kernel_main.o
CC = i686-elf-gcc # cross-compiler CC = i686-elf-gcc # cross-compiler
CFLAGS = -m32 -fno-stack-protector -ffreestanding -Wall -Wextra -Werror -g -c CFLAGS = -m32 -fno-stack-protector -ffreestanding -Wall -Wextra -Werror -g -c
all: ${OBJS} all: ${OBJS}
%.o: %.c %.o: %.c
$(CC) $(CFLAGS) $< -o $@ $(CC) $(CFLAGS) $< -o $@

View File

@ -1,8 +1,9 @@
OBJS = kernel_loader.asm.o ports.asm.o \ OBJS = main.asm.o ports.asm.o \
gdt.asm.o idt.asm.o interrupts.asm.o gdt.asm.o idt.asm.o \
interrupts.asm.o header.asm.o
ASM = nasm
ASMFLAGS = -f elf32 ASM = nasm
all: $(OBJS) ASMFLAGS = -f elf32
%.asm.o: %.asm all: $(OBJS)
$(ASM) $(ASMFLAGS) $< -o $@ %.asm.o: %.asm
$(ASM) $(ASMFLAGS) $< -o $@

View File

@ -1,22 +1,22 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; vulcanOS Kernel ; ; vulcanOS Kernel ;
; Developed by Marco 'icebit' Cetica ; ; Developed by Marco 'icebit' Cetica ;
; (c) 2019-2021 ; ; (c) 2019-2021 ;
; Released under GPLv3 ; ; Released under GPLv3 ;
; https://github.com/ice-bit/iceOS ; ; https://github.com/ice-bit/vulcanos ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
global gdt_flush ; for drivers/gdt.c global gdt_flush ; for drivers/gdt.c
section .text section .text
gdt_flush: gdt_flush:
mov eax, [esp+4] ; get address of gdt_ptr_t mov eax, [esp+4] ; get address of gdt_ptr_t
lgdt [eax] ; Load GDT lgdt [eax] ; Load GDT
mov ax, 0x10 ; offset in the GDT of the data segment mov ax, 0x10 ; offset in the GDT of the data segment
mov ds, ax ; Load data segment selectors mov ds, ax ; Load data segment selectors
mov es, ax mov es, ax
mov fs, ax mov fs, ax
mov gs, ax mov gs, ax
mov ss, ax mov ss, ax
jmp 0x08:.flush ; offset in the GDT of the code segment jmp 0x08:.flush ; offset in the GDT of the code segment
.flush: .flush:
ret ret

19
kernel/cpu/header.asm Normal file
View File

@ -0,0 +1,19 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; vulcanOS Kernel ;
; Developed by Marco 'icebit' Cetica ;
; (c) 2019-2021 ;
; Released under GPLv3 ;
; https://github.com/ice-bit/vulcanos ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
section .multiboot_header
header_s:
dd 0xE85250D6 ; Magic number for multiboot
dd 0 ; Protected mode flag
dd header_e - header_s ; Header length
dd 0x100000000 - (0xE85250D6 + 0 + (header_e - header_s)) ; Checksum
; Other flags
dw 0 ; Type
dw 0 ; Flags
dw 0 ; Size
header_e:

View File

@ -1,14 +1,14 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; vulcanOS Kernel ; ; vulcanOS Kernel ;
; Developed by Marco 'icebit' Cetica ; ; Developed by Marco 'icebit' Cetica ;
; (c) 2019-2021 ; ; (c) 2019-2021 ;
; Released under GPLv3 ; ; Released under GPLv3 ;
; https://github.com/ice-bit/iceOS ; ; https://github.com/ice-bit/vulcanos ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
global idt_flush ; for drivers/idt.c global idt_flush ; for drivers/idt.c
section .text section .text
idt_flush: idt_flush:
mov eax, [esp+4] ; Retrieve idt_ptr_t* mov eax, [esp+4] ; Retrieve idt_ptr_t*
lidt [eax] lidt [eax]
ret ret

View File

@ -1,159 +1,159 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; vulcanOS Kernel ; ; vulcanOS Kernel ;
; Developed by Marco 'icebit' Cetica ; ; Developed by Marco 'icebit' Cetica ;
; (c) 2019-2021 ; ; (c) 2019-2021 ;
; Released under GPLv3 ; ; Released under GPLv3 ;
; https://github.com/ice-bit/iceOS ; ; https://github.com/ice-bit/vulcanos ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
extern isr_handler ; Defined in drivers/isr.h extern isr_handler ; Defined in drivers/isr.h
extern irq_handler ; Defined in drivers/isr.h extern irq_handler ; Defined in drivers/isr.h
; Let's implement all ISR in a very handy way ; Let's implement all ISR in a very handy way
%macro ISR_NOERRCODE 1 %macro ISR_NOERRCODE 1
global isr%1 global isr%1
isr%1: isr%1:
cli ; Disable interrupts cli ; Disable interrupts
push byte 0 ; Push dummy error code push byte 0 ; Push dummy error code
push byte %1 ; Push interrupt number push byte %1 ; Push interrupt number
jmp isr_common ; goto ISR handler jmp isr_common ; goto ISR handler
%endmacro %endmacro
%macro ISR_ERRCODE 1 %macro ISR_ERRCODE 1
global isr%1 global isr%1
isr%1: isr%1:
cli ; Disable interrupts cli ; Disable interrupts
push byte %1 ; Push interrupt number push byte %1 ; Push interrupt number
jmp isr_common ; goto ISR handler jmp isr_common ; goto ISR handler
%endmacro %endmacro
; Now we have to do the same thing for Interrupt Requests, ; Now we have to do the same thing for Interrupt Requests,
; in this case the first parameter is the IRQ number while ; in this case the first parameter is the IRQ number while
; the second one is the ISR number to be remapped to ; the second one is the ISR number to be remapped to
%macro IRQ 2 %macro IRQ 2
global irq%1 global irq%1
irq%1: irq%1:
cli ; Disable interrupts cli ; Disable interrupts
push byte 0 ; Push dummy error code push byte 0 ; Push dummy error code
push byte %2 ; Push interrupt number push byte %2 ; Push interrupt number
jmp irq_common ; goto IRQ handler jmp irq_common ; goto IRQ handler
%endmacro %endmacro
; isr_common is a common handler for all ; isr_common is a common handler for all
; Interrupt Service Routines declared in the system ; Interrupt Service Routines declared in the system
; It's main scope is to save current register's states ; It's main scope is to save current register's states
; into the stack, call the C high level handler ; into the stack, call the C high level handler
; and restore the register's original values from ; and restore the register's original values from
; the stack ; the stack
isr_common: isr_common:
;; Save register's content into the stack ;; ;; Save register's content into the stack ;;
pusha ; Push edi,esi,ebp,esp,ebx,edx,ecx,eax pusha ; Push edi,esi,ebp,esp,ebx,edx,ecx,eax
mov ax, ds ; Get 16 bits of eax(e.g ds) mov ax, ds ; Get 16 bits of eax(e.g ds)
push eax push eax
mov ax, 0x10 ; Load the kernel data segment descriptor mov ax, 0x10 ; Load the kernel data segment descriptor
mov ds, ax mov ds, ax
mov es, ax mov es, ax
mov fs, ax mov fs, ax
mov gs, ax mov gs, ax
;; Call C handler ;; ;; Call C handler ;;
call isr_handler ; Call C handler call isr_handler ; Call C handler
;; Restore register's content from the stack ;; ;; Restore register's content from the stack ;;
pop eax ; Restore original data segment selector pop eax ; Restore original data segment selector
mov ds, ax mov ds, ax
mov es, ax mov es, ax
mov fs, ax mov fs, ax
mov gs, ax mov gs, ax
popa ; Pop edi,esi,ebp,esp,ebx,edx,ecx,eax popa ; Pop edi,esi,ebp,esp,ebx,edx,ecx,eax
add esp, 8 ; Cleans up pushed error code and ISR number add esp, 8 ; Cleans up pushed error code and ISR number
sti ; Re-enable interrupts sti ; Re-enable interrupts
iret ; Pops 5 things: CS, EIP, EFLAGS, SS and ESp iret ; Pops 5 things: CS, EIP, EFLAGS, SS and ESp
; irq_common is a common handler for all ; irq_common is a common handler for all
; Interrupt Requests, it's very similar to the ; Interrupt Requests, it's very similar to the
; ISR one ; ISR one
irq_common: irq_common:
;; Save register's content into the stack ;; ;; Save register's content into the stack ;;
pusha ; Push edi,esi,ebp,esp,ebx,edx,ecx,eax pusha ; Push edi,esi,ebp,esp,ebx,edx,ecx,eax
mov ax, ds ; Get 16 bits of eax(e.g ds) mov ax, ds ; Get 16 bits of eax(e.g ds)
push eax push eax
mov ax, 0x10 ; Load the kernel data segment descriptor mov ax, 0x10 ; Load the kernel data segment descriptor
mov ds, ax mov ds, ax
mov es, ax mov es, ax
mov fs, ax mov fs, ax
mov gs, ax mov gs, ax
;; Call C handler ;; ;; Call C handler ;;
call irq_handler ; Call C handler call irq_handler ; Call C handler
;; Restore register's content from the stack ;; ;; Restore register's content from the stack ;;
pop ebx ; Restore original data segment selector pop ebx ; Restore original data segment selector
mov ds, bx mov ds, bx
mov es, bx mov es, bx
mov fs, bx mov fs, bx
mov gs, bx mov gs, bx
popa ; Pop edi,esi,ebp,esp,ebx,edx,ecx,eax popa ; Pop edi,esi,ebp,esp,ebx,edx,ecx,eax
add esp, 8 ; Cleans up pushed error code and ISR number add esp, 8 ; Cleans up pushed error code and ISR number
sti ; Re-enable interrupts sti ; Re-enable interrupts
iret ; Pops 5 things: CS, EIP, EFLAGS, SS and ESp iret ; Pops 5 things: CS, EIP, EFLAGS, SS and ESp
; Standard x86 ISRs (only 8,10-14 and 17 requires to push error codes to the stack) ; Standard x86 ISRs (only 8,10-14 and 17 requires to push error codes to the stack)
ISR_NOERRCODE 0 ISR_NOERRCODE 0
ISR_NOERRCODE 1 ISR_NOERRCODE 1
ISR_NOERRCODE 2 ISR_NOERRCODE 2
ISR_NOERRCODE 3 ISR_NOERRCODE 3
ISR_NOERRCODE 4 ISR_NOERRCODE 4
ISR_NOERRCODE 5 ISR_NOERRCODE 5
ISR_NOERRCODE 6 ISR_NOERRCODE 6
ISR_NOERRCODE 7 ISR_NOERRCODE 7
ISR_ERRCODE 8 ISR_ERRCODE 8
ISR_NOERRCODE 9 ISR_NOERRCODE 9
ISR_ERRCODE 10 ISR_ERRCODE 10
ISR_ERRCODE 11 ISR_ERRCODE 11
ISR_ERRCODE 12 ISR_ERRCODE 12
ISR_ERRCODE 13 ISR_ERRCODE 13
ISR_ERRCODE 14 ISR_ERRCODE 14
ISR_NOERRCODE 15 ISR_NOERRCODE 15
ISR_NOERRCODE 16 ISR_NOERRCODE 16
ISR_NOERRCODE 17 ISR_NOERRCODE 17
ISR_NOERRCODE 18 ISR_NOERRCODE 18
ISR_NOERRCODE 19 ISR_NOERRCODE 19
ISR_NOERRCODE 20 ISR_NOERRCODE 20
ISR_NOERRCODE 21 ISR_NOERRCODE 21
ISR_NOERRCODE 22 ISR_NOERRCODE 22
ISR_NOERRCODE 23 ISR_NOERRCODE 23
ISR_NOERRCODE 24 ISR_NOERRCODE 24
ISR_NOERRCODE 25 ISR_NOERRCODE 25
ISR_NOERRCODE 26 ISR_NOERRCODE 26
ISR_NOERRCODE 27 ISR_NOERRCODE 27
ISR_NOERRCODE 28 ISR_NOERRCODE 28
ISR_NOERRCODE 29 ISR_NOERRCODE 29
ISR_NOERRCODE 30 ISR_NOERRCODE 30
ISR_NOERRCODE 31 ISR_NOERRCODE 31
IRQ 0, 32 IRQ 0, 32
IRQ 1, 33 IRQ 1, 33
IRQ 2, 34 IRQ 2, 34
IRQ 3, 35 IRQ 3, 35
IRQ 4, 36 IRQ 4, 36
IRQ 5, 37 IRQ 5, 37
IRQ 6, 38 IRQ 6, 38
IRQ 7, 39 IRQ 7, 39
IRQ 8, 40 IRQ 8, 40
IRQ 9, 41 IRQ 9, 41
IRQ 10, 42 IRQ 10, 42
IRQ 11, 43 IRQ 11, 43
IRQ 12, 44 IRQ 12, 44
IRQ 13, 45 IRQ 13, 45
IRQ 14, 46 IRQ 14, 46
IRQ 15, 47 IRQ 15, 47

View File

@ -1,43 +0,0 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; vulcanOS Kernel ;
; Developed by Marco 'icebit' Cetica ;
; (c) 2019-2021 ;
; Released under GPLv3 ;
; https://github.com/ice-bit/iceOS ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
[BITS 32] ; We should be in protected mode
section .multiboot
head_s:
dd 0xE85250D6 ; Multiboot header magic number
dd 0 ; Protected mode flag
dd head_e - head_s ; Header length
dd 0x100000000 - (0xE85250D6 + 0 + (head_e - head_s)) ; Checksum of above
; Other flags
dw 0 ; type
dw 0 ; flags
dd 0 ; size
head_e:
GLOBAL kernel_loader
EXTERN kernel_main
section .text
kernel_loader:
mov esp, kernel_stack + KERNEL_STACK_SZ ; Define stack pointer
push eax ; Set multiboot header
call kernel_main ; Jump into kernel's main function
.loop:
jmp .loop ; If the kernel returns, go into an infinite loop.
; This will prevent the CPU to run non-kernel instructions
; from the memory
KERNEL_STACK_SZ equ 4096 ; Stack size(4KiB)
section .bss
align 4
kernel_stack:
resb KERNEL_STACK_SZ ; Reserve 4 KiB

27
kernel/cpu/main.asm Normal file
View File

@ -0,0 +1,27 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; vulcanOS Kernel ;
; Developed by Marco 'icebit' Cetica ;
; (c) 2019-2021 ;
; Released under GPLv3 ;
; https://github.com/ice-bit/vulcanos ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
GLOBAL kernel_loader
EXTERN kernel_main
[BITS 32] ; Ensure we are in protected mode
section .text
kernel_loader:
mov esp, kernel_stack + KERNEL_STACK_SZ ; Define stack pointer
push eax ; Set multiboot header register
call kernel_main ; Call kernel's main function
.loop:
jmp .loop ; If the kernel returns, go into an endless loop
; This will prevent the CPU to execure any non-kernel
; instructions.
KERNEL_STACK_SZ equ 4096 ; Stack size(4KiB)
section .bss
align 4
kernel_stack:
resb KERNEL_STACK_SZ ; Reserver 4KiB for kernel's stack

View File

@ -1,21 +1,21 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; vulcanOS Kernel ; ; vulcanOS Kernel ;
; Developed by Marco 'icebit' Cetica ; ; Developed by Marco 'icebit' Cetica ;
; (c) 2019-2021 ; ; (c) 2019-2021 ;
; Released under GPLv3 ; ; Released under GPLv3 ;
; https://github.com/ice-bit/iceOS ; ; https://github.com/ice-bit/vulcanos ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
global outb ; Output from port global outb ; Output from port
global inb ; Input to port global inb ; Input to port
outb: outb:
mov al, [esp + 8] mov al, [esp + 8]
mov dx, [esp + 4] mov dx, [esp + 4]
out dx, al out dx, al
ret ret
inb: inb:
mov dx, [esp + 4] mov dx, [esp + 4]
in al, dx in al, dx
ret ret

View File

@ -1,11 +1,11 @@
OBJS = tty.o gdt.o idt.o isr.o timer.o keyboard.o \ OBJS = tty.o gdt.o idt.o isr.o timer.o keyboard.o \
fs.o cpuid.o fs.o cpuid.o
CC = i686-elf-gcc # cross-compiler CC = i686-elf-gcc # cross-compiler
CFLAGS = -m32 -fno-stack-protector -DDEFAULT_USER=root -DDEFAULT_HOSTNAME=vulcan -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} all:${OBJS}
%.o: %.c %.o: %.c
$(CC) $(CFLAGS) $< -o $@ $(CC) $(CFLAGS) $< -o $@

View File

@ -1,195 +1,195 @@
#include "cpuid.h" #include "cpuid.h"
#include "../libc/string.h" #include "../libc/string.h"
#define INTEL_MAGIC_NUMBER 0x756e6547 #define INTEL_MAGIC_NUMBER 0x756e6547
#define AMD_MAGIC_NUMBER 0x68747541 #define AMD_MAGIC_NUMBER 0x68747541
#define UNRECOGNIZED_CPU 0xBADFF #define UNRECOGNIZED_CPU 0xBADFF
static cpuid_t get_cpuid(icpuid_t cpu); static cpuid_t get_cpuid(icpuid_t cpu);
static icpuid_t detect_cpu(void); static icpuid_t detect_cpu(void);
static icpuid_t intel_cpu(void); static icpuid_t intel_cpu(void);
static icpuid_t amd_cpu(void); static icpuid_t amd_cpu(void);
static icpuid_t generic_cpu(void); static icpuid_t generic_cpu(void);
icpuid_t detect_cpu(void) { icpuid_t detect_cpu(void) {
uint32_t ebx, null; uint32_t ebx, null;
icpuid_t i_cpu; icpuid_t i_cpu;
cpuid(0, null, ebx, null, null); cpuid(0, null, ebx, null, null);
// Select CPU brand // Select CPU brand
switch(ebx) { switch(ebx) {
case INTEL_MAGIC_NUMBER: case INTEL_MAGIC_NUMBER:
i_cpu = intel_cpu(); i_cpu = intel_cpu();
break; break;
case AMD_MAGIC_NUMBER: case AMD_MAGIC_NUMBER:
i_cpu = amd_cpu(); i_cpu = amd_cpu();
break; break;
default: default:
i_cpu = generic_cpu(); i_cpu = generic_cpu();
break; break;
} }
return i_cpu; return i_cpu;
} }
icpuid_t intel_cpu(void) { icpuid_t intel_cpu(void) {
uint32_t eax, ebx, null; uint32_t eax, ebx, null;
icpuid_t icpu; icpuid_t icpu;
// Fill the structure // Fill the structure
cpuid(1, eax, ebx, null, null); cpuid(1, eax, ebx, null, null);
icpu.model = (eax >> 4) & 0xF; icpu.model = (eax >> 4) & 0xF;
icpu.family = (eax >> 8) & 0xF; icpu.family = (eax >> 8) & 0xF;
icpu.type = (eax >> 12) & 0xF; icpu.type = (eax >> 12) & 0xF;
icpu.brand = INTEL_MAGIC_NUMBER; icpu.brand = INTEL_MAGIC_NUMBER;
icpu.stepping = eax & 0xF; icpu.stepping = eax & 0xF;
icpu.reserved = eax >> 14; icpu.reserved = eax >> 14;
return icpu; return icpu;
} }
icpuid_t amd_cpu(void) { icpuid_t amd_cpu(void) {
uint32_t eax, null; uint32_t eax, null;
icpuid_t icpu; icpuid_t icpu;
// Fill the structure // Fill the structure
cpuid(1, eax, null, null, null); cpuid(1, eax, null, null, null);
icpu.model = (eax >> 4) & 0xF; icpu.model = (eax >> 4) & 0xF;
icpu.family = (eax >> 8) & 0xF; icpu.family = (eax >> 8) & 0xF;
icpu.stepping = eax & 0xF; icpu.stepping = eax & 0xF;
icpu.reserved = eax >> 12; icpu.reserved = eax >> 12;
icpu.brand = AMD_MAGIC_NUMBER; icpu.brand = AMD_MAGIC_NUMBER;
return icpu; return icpu;
} }
icpuid_t generic_cpu(void) { icpuid_t generic_cpu(void) {
icpuid_t icpu; icpuid_t icpu;
icpu.brand = UNRECOGNIZED_CPU; // Magic number for unknown CPUs icpu.brand = UNRECOGNIZED_CPU; // Magic number for unknown CPUs
return icpu; return icpu;
} }
cpuid_t get_cpuid(icpuid_t cpu) { cpuid_t get_cpuid(icpuid_t cpu) {
cpuid_t cpuid; cpuid_t cpuid;
uint8_t model[64]; uint8_t model[64];
// Recognize CPU brand // Recognize CPU brand
if(cpu.brand == AMD_MAGIC_NUMBER) { if(cpu.brand == AMD_MAGIC_NUMBER) {
switch(cpu.family) { switch(cpu.family) {
case 4: case 4:
strcpy(model, (uint8_t*)"486 model "); // Set model name strcpy(model, (uint8_t*)"486 model "); // Set model name
strcat(model, (void*)cpu.model); // Set model version strcat(model, (void*)cpu.model); // Set model version
cpuid.model = model; cpuid.model = model;
break; break;
case 5: case 5:
switch(cpu.model) { switch(cpu.model) {
case 0: case 0:
case 1: case 1:
case 2: case 2:
case 3: case 3:
case 4: case 4:
case 5: case 5:
case 6: case 6:
case 7: case 7:
strcpy(model, (uint8_t*)"K6 model "); // Set model name strcpy(model, (uint8_t*)"K6 model "); // Set model name
strcat(model, (void*)cpu.model); // Set model version strcat(model, (void*)cpu.model); // Set model version
cpuid.model = model; cpuid.model = model;
break; break;
case 8: case 8:
strcpy(model, (uint8_t*)"K6-2 model "); // Set model name strcpy(model, (uint8_t*)"K6-2 model "); // Set model name
strcat(model, (void*)cpu.model); // Set model version strcat(model, (void*)cpu.model); // Set model version
cpuid.model = model; cpuid.model = model;
break; break;
case 9: case 9:
strcpy(model, (uint8_t*)"K6-III model "); // Set model name strcpy(model, (uint8_t*)"K6-III model "); // Set model name
strcat(model, (void*)cpu.model); // Set model version strcat(model, (void*)cpu.model); // Set model version
cpuid.model = model; cpuid.model = model;
break; break;
default: default:
strcpy(model, (uint8_t*)"K5/K6 model "); // Set model name strcpy(model, (uint8_t*)"K5/K6 model "); // Set model name
strcat(model, (void*)cpu.model); // Set model version strcat(model, (void*)cpu.model); // Set model version
cpuid.model = model; cpuid.model = model;
break; break;
} }
break; break;
case 6: case 6:
switch(cpu.model) { switch(cpu.model) {
case 1: case 1:
case 2: case 2:
case 3: case 3:
cpuid.model = (uint8_t*)"Duron model 3"; cpuid.model = (uint8_t*)"Duron model 3";
break; break;
case 4: case 4:
strcpy(model, (uint8_t*)"Athlon model "); strcpy(model, (uint8_t*)"Athlon model ");
strcat(model, (void*)cpu.model); strcat(model, (void*)cpu.model);
cpuid.model = model; cpuid.model = model;
break; break;
case 6: case 6:
cpuid.model = (uint8_t*)"Athlon MP/Mobile Athlon Model 6"; cpuid.model = (uint8_t*)"Athlon MP/Mobile Athlon Model 6";
break; break;
case 7: case 7:
cpuid.model = (uint8_t*)"Mobile Duron Model 7"; cpuid.model = (uint8_t*)"Mobile Duron Model 7";
break; break;
default: default:
strcpy(model, (uint8_t*)"Duron/Athlon model "); strcpy(model, (uint8_t*)"Duron/Athlon model ");
strcat(model, (void*)cpu.model); strcat(model, (void*)cpu.model);
cpuid.model = model; cpuid.model = model;
break; break;
} }
break; break;
} }
} else if(cpu.brand == INTEL_MAGIC_NUMBER) { } else if(cpu.brand == INTEL_MAGIC_NUMBER) {
switch(cpu.type) { switch(cpu.type) {
case 0: case 0:
cpuid.type =(uint8_t*)"Original OEM"; cpuid.type =(uint8_t*)"Original OEM";
break; break;
case 1: case 1:
cpuid.type = (uint8_t*)"Overdrive"; cpuid.type = (uint8_t*)"Overdrive";
break; break;
case 2: case 2:
cpuid.type = (uint8_t*)"Dual-capable"; cpuid.type = (uint8_t*)"Dual-capable";
break; break;
case 3: case 3:
cpuid.type = (uint8_t*)"Reserved"; cpuid.type = (uint8_t*)"Reserved";
break; break;
} }
switch(cpu.family) { switch(cpu.family) {
case 3: case 3:
cpuid.family = (uint8_t*)"i386"; cpuid.family = (uint8_t*)"i386";
break; break;
case 4: case 4:
cpuid.family = (uint8_t*)"i486"; cpuid.family = (uint8_t*)"i486";
break; break;
case 5: case 5:
cpuid.family = (uint8_t*)"Pentium II Model 5/Xeon/Celeron"; cpuid.family = (uint8_t*)"Pentium II Model 5/Xeon/Celeron";
break; break;
case 6: case 6:
cpuid.family = (uint8_t*)"Pentium Pro"; cpuid.family = (uint8_t*)"Pentium Pro";
break; break;
case 15: case 15:
cpuid.family = (uint8_t*)"Pentium 4"; cpuid.family = (uint8_t*)"Pentium 4";
break; break;
} }
} else if(cpu.brand == UNRECOGNIZED_CPU) } else if(cpu.brand == UNRECOGNIZED_CPU)
cpuid.family = (uint8_t*)"Generic (x86) CPU"; cpuid.family = (uint8_t*)"Generic (x86) CPU";
return cpuid; return cpuid;
} }
uint8_t *get_cpu_type() { uint8_t *get_cpu_type() {
icpuid_t icpu = detect_cpu(); // Detect CPU brand(Intel, AMD or generic x86) icpuid_t icpu = detect_cpu(); // Detect CPU brand(Intel, AMD or generic x86)
cpuid_t cpu_type = get_cpuid(icpu); cpuid_t cpu_type = get_cpuid(icpu);
return (uint8_t*)cpu_type.type; return (uint8_t*)cpu_type.type;
} }
uint8_t *get_cpu_family() { uint8_t *get_cpu_family() {
icpuid_t icpu = detect_cpu(); // Detect CPU brand(Intel, AMD or generic x86) icpuid_t icpu = detect_cpu(); // Detect CPU brand(Intel, AMD or generic x86)
cpuid_t cpu_family = get_cpuid(icpu); cpuid_t cpu_family = get_cpuid(icpu);
return (uint8_t*)cpu_family.family; return (uint8_t*)cpu_family.family;
} }

View File

@ -1,36 +1,36 @@
/************************************** /*****************************************
* VulcanOS Kernel * * VulcanOS Kernel *
* Developed by Marco 'icebit' Cetica * * Developed by Marco 'icebit' Cetica *
* (c) 2019-2021 * * (c) 2019-2021 *
* Released under GPLv3 * * Released under GPLv3 *
* https://github.com/ice-bit/iceOS * * https://github.com/ice-bit/vulcanos *
***************************************/ *****************************************/
#ifndef CPUID_H #ifndef CPUID_H
#define CPUID_H #define CPUID_H
#include <stdint.h> #include <stdint.h>
#define cpuid(in, a, b, c, d) __asm__("cpuid": "=a" (a), "=b"(b), "=d" (d) : "a" (in)); #define cpuid(in, a, b, c, d) __asm__("cpuid": "=a" (a), "=b"(b), "=d" (d) : "a" (in));
typedef struct { typedef struct {
uint32_t model; uint32_t model;
uint32_t family; uint32_t family;
uint32_t type; uint32_t type;
uint32_t brand; uint32_t brand;
uint32_t stepping; uint32_t stepping;
uint32_t reserved; uint32_t reserved;
} icpuid_t; } icpuid_t;
typedef struct { typedef struct {
uint8_t *model; uint8_t *model;
uint8_t *family; uint8_t *family;
uint8_t *type; uint8_t *type;
uint8_t *brand; uint8_t *brand;
uint8_t *stepping; uint8_t *stepping;
uint8_t *reserved; uint8_t *reserved;
} cpuid_t; } cpuid_t;
// return type and family processor // return type and family processor
uint8_t *get_cpu_type(); uint8_t *get_cpu_type();
uint8_t *get_cpu_family(); uint8_t *get_cpu_family();
#endif #endif

View File

@ -1,47 +1,47 @@
#include "fs.h" #include "fs.h"
fs_node_t *fs_root = 0; // Initialize the root of the filesystem fs_node_t *fs_root = 0; // Initialize the root of the filesystem
uint32_t read_fs(fs_node_t *node, uint32_t offset, uint32_t size, uint8_t *buffer) { uint32_t read_fs(fs_node_t *node, uint32_t offset, uint32_t size, uint8_t *buffer) {
// Check if inode got a read callback from the kernel // Check if inode got a read callback from the kernel
if(node->read != 0) if(node->read != 0)
return node->read(node, offset, size, buffer); return node->read(node, offset, size, buffer);
else else
return 0; return 0;
} }
uint32_t write_fs(fs_node_t *node, uint32_t offset, uint32_t size, uint8_t *buffer) { uint32_t write_fs(fs_node_t *node, uint32_t offset, uint32_t size, uint8_t *buffer) {
// Check if inode got a write callback from the kernel // Check if inode got a write callback from the kernel
if(node->write != 0) if(node->write != 0)
return node->write(node, offset, size, buffer); return node->write(node, offset, size, buffer);
else else
return 0; return 0;
} }
void open_fs(fs_node_t *node) { void open_fs(fs_node_t *node) {
// Check if inode got a open callback from the kernel // Check if inode got a open callback from the kernel
if(node->open != 0) if(node->open != 0)
return node->open(node); return node->open(node);
} }
void close_fs(fs_node_t *node) { void close_fs(fs_node_t *node) {
// Check if inode got a close callback from the kernel // Check if inode got a close callback from the kernel
if(node->close != 0) if(node->close != 0)
return node->close(node); return node->close(node);
} }
struct dirent *readdir_fs(fs_node_t *node, uint32_t index) { struct dirent *readdir_fs(fs_node_t *node, uint32_t index) {
// Read dir content(only if file descriptor is FS_DIRECTORY) // Read dir content(only if file descriptor is FS_DIRECTORY)
if((node->flags&0x7) == FS_DIRECTORY && node->readdir != 0) if((node->flags&0x7) == FS_DIRECTORY && node->readdir != 0)
return node->readdir(node, index); return node->readdir(node, index);
else else
return 0; return 0;
} }
fs_node_t *finddir_fs(fs_node_t *node, char *name) { fs_node_t *finddir_fs(fs_node_t *node, char *name) {
// Check if an inode is a directory // Check if an inode is a directory
if((node->flags&0x7) == FS_DIRECTORY && node->finddir != 0) if((node->flags&0x7) == FS_DIRECTORY && node->finddir != 0)
return node->finddir(node, name); return node->finddir(node, name);
else else
return 0; return 0;
} }

View File

@ -1,84 +1,84 @@
/************************************** /*****************************************
* VulcanOS Kernel * * VulcanOS Kernel *
* Developed by Marco 'icebit' Cetica * * Developed by Marco 'icebit' Cetica *
* (c) 2019-2021 * * (c) 2019-2021 *
* Released under GPLv3 * * Released under GPLv3 *
* https://github.com/ice-bit/iceOS * * https://github.com/ice-bit/vulcanos *
***************************************/ *****************************************/
#ifndef FS_H #ifndef FS_H
#define FS_H #define FS_H
#include <stdint.h> #include <stdint.h>
/* This Virtual File System(VFS) is a simplified version of /* This Virtual File System(VFS) is a simplified version of
* standard UNIX VFS where all files comes organized in a graph * standard UNIX VFS where all files comes organized in a graph
* of nodes. Keeping in mind the concept of "everything is a file" we can * of nodes. Keeping in mind the concept of "everything is a file" we can
* store a file, a directory, a serial device or anything else just by adding * store a file, a directory, a serial device or anything else just by adding
* a new node to the data structure. * a new node to the data structure.
* And this is a list of common operations: * And this is a list of common operations:
* - Open: Initialize a new node as a file descriptor * - Open: Initialize a new node as a file descriptor
* - Close: CLose a node * - Close: CLose a node
* - Read: return the content of a node * - Read: return the content of a node
* - Write: set content to node * - Write: set content to node
* - Readdir: Return directory content * - Readdir: Return directory content
* - Finddir: Given a specific name find the corresponding child node.*/ * - Finddir: Given a specific name find the corresponding child node.*/
// Define some standard node types // Define some standard node types
#define FS_FILE 0x01 #define FS_FILE 0x01
#define FS_DIRECTORY 0x02 #define FS_DIRECTORY 0x02
#define FS_CHARDEVICE 0x03 #define FS_CHARDEVICE 0x03
#define FS_BLOCKDEVICE 0x04 #define FS_BLOCKDEVICE 0x04
#define FS_PIPE 0x05 #define FS_PIPE 0x05
#define FS_SYMLINK 0x06 #define FS_SYMLINK 0x06
#define FS_MOUNTPOINT 0x08 #define FS_MOUNTPOINT 0x08
struct fs_node; struct fs_node;
/* Define some callbacks to be called when read/write/open/close /* Define some callbacks to be called when read/write/open/close
* operations are called */ * operations are called */
typedef uint32_t (*read_type_t)(struct fs_node*, uint32_t, uint32_t, uint8_t*); typedef uint32_t (*read_type_t)(struct fs_node*, uint32_t, uint32_t, uint8_t*);
typedef uint32_t (*write_type_t)(struct fs_node*, uint32_t, uint32_t, uint8_t*); typedef uint32_t (*write_type_t)(struct fs_node*, uint32_t, uint32_t, uint8_t*);
typedef void (*open_type_t)(struct fs_node*); typedef void (*open_type_t)(struct fs_node*);
typedef void (*close_type_t)(struct fs_node*); typedef void (*close_type_t)(struct fs_node*);
typedef struct dirent*(*readdir_type_t)(struct fs_node*, uint32_t); typedef struct dirent*(*readdir_type_t)(struct fs_node*, uint32_t);
typedef struct fs_node*(*finddir_type_t)(struct fs_node*, char *name); typedef struct fs_node*(*finddir_type_t)(struct fs_node*, char *name);
// This define the structure of a node // This define the structure of a node
typedef struct fs_node { typedef struct fs_node {
uint8_t name[128]; // File name uint8_t name[128]; // File name
uint32_t mask; // Permission mask uint32_t mask; // Permission mask
uint32_t uid; // Owning user uint32_t uid; // Owning user
uint32_t gid; // Owning group uint32_t gid; // Owning group
uint32_t flags; // Node type uint32_t flags; // Node type
uint32_t inode; // used by file systems to identify files uint32_t inode; // used by file systems to identify files
uint32_t length; // Length of the file, in bytes. uint32_t length; // Length of the file, in bytes.
uint32_t impl; uint32_t impl;
// Callback section // Callback section
read_type_t read; read_type_t read;
write_type_t write; write_type_t write;
open_type_t open; open_type_t open;
close_type_t close; close_type_t close;
readdir_type_t readdir; readdir_type_t readdir;
finddir_type_t finddir; finddir_type_t finddir;
struct fs_node *ptr; // Used by mountpoints and symlinks struct fs_node *ptr; // Used by mountpoints and symlinks
} fs_node_t; } fs_node_t;
struct dirent { struct dirent {
uint8_t name[120]; // File name uint8_t name[120]; // File name
uint32_t ino; // POSIX standard requires inode number; uint32_t ino; // POSIX standard requires inode number;
}; };
// Filesystem root // Filesystem root
extern fs_node_t *fs_root; extern fs_node_t *fs_root;
/* Write/Read/Open/Close operations /* Write/Read/Open/Close operations
* NOTE: those functions are NOT like the Callback * NOTE: those functions are NOT like the Callback
* functions; the first one deals with inodes while * functions; the first one deals with inodes while
* the second one deals with file descriptors. */ * the second one deals with file descriptors. */
uint32_t read_fs(fs_node_t *node, uint32_t offset, uint32_t size, uint8_t *buffer); uint32_t read_fs(fs_node_t *node, uint32_t offset, uint32_t size, uint8_t *buffer);
uint32_t write_fs(fs_node_t *node, uint32_t offset, uint32_t size, uint8_t *buffer); uint32_t write_fs(fs_node_t *node, uint32_t offset, uint32_t size, uint8_t *buffer);
void open_fs(fs_node_t *node); void open_fs(fs_node_t *node);
void close_fs(fs_node_t *node); void close_fs(fs_node_t *node);
struct dirent *readdir_fs(fs_node_t *node, uint32_t index); struct dirent *readdir_fs(fs_node_t *node, uint32_t index);
fs_node_t *finddir_fs(fs_node_t *node, char *name); fs_node_t *finddir_fs(fs_node_t *node, char *name);
#endif #endif

View File

@ -1,103 +1,103 @@
#include "gdt.h" #include "gdt.h"
// Internal method // Internal method
extern void gdt_flush(uint32_t); // Defined on cpu/gdt.asm extern void gdt_flush(uint32_t); // Defined on cpu/gdt.asm
static gdt_entry_t construct_null_entry(); static gdt_entry_t construct_null_entry();
static gdt_entry_t construct_entry(gdt_access_t access); static gdt_entry_t construct_entry(gdt_access_t access);
static void init_gdt(); static void init_gdt();
gdt_entry_t gdt_entries[5]; gdt_entry_t gdt_entries[5];
gdt_ptr_t gdt_ptr; gdt_ptr_t gdt_ptr;
// This method will be called by the kernel // This method will be called by the kernel
void gdt_setup() { void gdt_setup() {
init_gdt(); init_gdt();
} }
static void init_gdt() { static void init_gdt() {
gdt_ptr.limit = (sizeof(gdt_entry_t) * 5) - 1; gdt_ptr.limit = (sizeof(gdt_entry_t) * 5) - 1;
gdt_ptr.base = (uint32_t)&gdt_entries; gdt_ptr.base = (uint32_t)&gdt_entries;
gdt_entry_t null_segment = construct_null_entry(); gdt_entry_t null_segment = construct_null_entry();
gdt_entry_t kernel_mode_code_segment = construct_entry( gdt_entry_t kernel_mode_code_segment = construct_entry(
(struct gdt_access){ (struct gdt_access){
.type = GDT_CODE_TYPE_EXEC_READ, .type = GDT_CODE_TYPE_EXEC_READ,
.dt = GDT_CODE_AND_DATA_DESCRIPTOR, .dt = GDT_CODE_AND_DATA_DESCRIPTOR,
.dpl = GDT_RING0, .dpl = GDT_RING0,
.p = GDT_SEGMENT_PRESENT .p = GDT_SEGMENT_PRESENT
} }
); );
gdt_entry_t kernel_mode_data_segment = construct_entry( gdt_entry_t kernel_mode_data_segment = construct_entry(
(struct gdt_access){ (struct gdt_access){
.type = GDT_DATA_TYPE_READ_WRITE, .type = GDT_DATA_TYPE_READ_WRITE,
.dt = GDT_CODE_AND_DATA_DESCRIPTOR, .dt = GDT_CODE_AND_DATA_DESCRIPTOR,
.dpl = GDT_RING0, .dpl = GDT_RING0,
.p = GDT_SEGMENT_PRESENT .p = GDT_SEGMENT_PRESENT
} }
); );
gdt_entry_t user_mode_code_segment = construct_entry( gdt_entry_t user_mode_code_segment = construct_entry(
(struct gdt_access){ (struct gdt_access){
.type = GDT_CODE_TYPE_EXEC_READ, .type = GDT_CODE_TYPE_EXEC_READ,
.dt = GDT_CODE_AND_DATA_DESCRIPTOR, .dt = GDT_CODE_AND_DATA_DESCRIPTOR,
.dpl = GDT_RING3, .dpl = GDT_RING3,
.p = GDT_SEGMENT_PRESENT .p = GDT_SEGMENT_PRESENT
} }
); );
gdt_entry_t user_mode_data_segment = construct_entry( gdt_entry_t user_mode_data_segment = construct_entry(
(struct gdt_access){ (struct gdt_access){
.type = GDT_DATA_TYPE_READ_WRITE, .type = GDT_DATA_TYPE_READ_WRITE,
.dt = GDT_CODE_AND_DATA_DESCRIPTOR, .dt = GDT_CODE_AND_DATA_DESCRIPTOR,
.dpl = GDT_RING3, .dpl = GDT_RING3,
.p = GDT_SEGMENT_PRESENT .p = GDT_SEGMENT_PRESENT
} }
); );
gdt_entries[0] = null_segment; gdt_entries[0] = null_segment;
gdt_entries[1] = kernel_mode_code_segment; gdt_entries[1] = kernel_mode_code_segment;
gdt_entries[2] = kernel_mode_data_segment; gdt_entries[2] = kernel_mode_data_segment;
gdt_entries[3] = user_mode_code_segment; gdt_entries[3] = user_mode_code_segment;
gdt_entries[4] = user_mode_data_segment; gdt_entries[4] = user_mode_data_segment;
gdt_flush((uint32_t)&gdt_ptr); gdt_flush((uint32_t)&gdt_ptr);
} }
static gdt_entry_t construct_entry(gdt_access_t access) { static gdt_entry_t construct_entry(gdt_access_t access) {
gdt_entry_t entry = (struct gdt_entry_struct) { gdt_entry_t entry = (struct gdt_entry_struct) {
.base_low = GDT_BASE & 0xFFFF, .base_low = GDT_BASE & 0xFFFF,
.base_middle = (GDT_BASE >> 16) & 0xFF, .base_middle = (GDT_BASE >> 16) & 0xFF,
.base_high = (GDT_BASE >> 24) & 0xFF, .base_high = (GDT_BASE >> 24) & 0xFF,
.limit_low = (GDT_LIMIT & 0xFFFF), .limit_low = (GDT_LIMIT & 0xFFFF),
.access = access, .access = access,
.granularity = (struct gdt_granularity) { .granularity = (struct gdt_granularity) {
.g = GDT_GRANULARITY_4K, .g = GDT_GRANULARITY_4K,
.d = GDT_OPERAND_SIZE_32, .d = GDT_OPERAND_SIZE_32,
.zero = 0, .zero = 0,
.seglen = GDT_SEGMENT_LENGTH .seglen = GDT_SEGMENT_LENGTH
} }
}; };
return entry; return entry;
} }
// The only difference is in the access // The only difference is in the access
static gdt_entry_t construct_null_entry() { static gdt_entry_t construct_null_entry() {
gdt_entry_t null_entry = (struct gdt_entry_struct) { gdt_entry_t null_entry = (struct gdt_entry_struct) {
.base_low = 0, .base_low = 0,
.base_middle = 0, .base_middle = 0,
.base_high = 0, .base_high = 0,
.limit_low = 0, .limit_low = 0,
.access = (struct gdt_access) { .access = (struct gdt_access) {
.p = 0, .p = 0,
.dpl = 0, .dpl = 0,
.dt = 0, .dt = 0,
.type = 0 .type = 0
}, },
.granularity = (struct gdt_granularity) { .granularity = (struct gdt_granularity) {
.g = 0, .g = 0,
.d = 0, .d = 0,
.zero = 0, .zero = 0,
.seglen = 0 .seglen = 0
} }
}; };
return null_entry; return null_entry;
} }

View File

@ -1,139 +1,139 @@
/************************************** /*****************************************
* VulcanOS Kernel * * VulcanOS Kernel *
* Developed by Marco 'icebit' Cetica * * Developed by Marco 'icebit' Cetica *
* (c) 2019-2021 * * (c) 2019-2021 *
* Released under GPLv3 * * Released under GPLv3 *
* https://github.com/ice-bit/iceOS * * https://github.com/ice-bit/vulcanos *
***************************************/ *****************************************/
#ifndef _GDT_H_ #ifndef _GDT_H_
#define _GDT_H_ #define _GDT_H_
#include <stdint.h> #include <stdint.h>
/* /*
* First a bit of theory: * First a bit of theory:
* GDT(Global Descriptor Table) is a complex data structure used in x86 systems * GDT(Global Descriptor Table) is a complex data structure used in x86 systems
* to define memory areas. * to define memory areas.
* Technically speaking GDT is formed by an array of 8-bytes segment descriptors, * Technically speaking GDT is formed by an array of 8-bytes segment descriptors,
* the first descriptor of the GDT is always a NULL one and CANNOT be used to allocate * the first descriptor of the GDT is always a NULL one and CANNOT be used to allocate
* memory; so we need at least two descriptors(plus the null descriptor) to successfully allocate * memory; so we need at least two descriptors(plus the null descriptor) to successfully allocate
* data on our memory. * data on our memory.
* In x86 architecture there're two methods to provide virtual memory: Segmentation and Paging: * In x86 architecture there're two methods to provide virtual memory: Segmentation and Paging:
* With the first one every memory access is done within his own segment, so each address(of a process) * With the first one every memory access is done within his own segment, so each address(of a process)
* is added to the segment's base address and checked against the segment's length. * is added to the segment's base address and checked against the segment's length.
* With paging, however, the address space is split into blocks(usually of 4KiB) called pages. * With paging, however, the address space is split into blocks(usually of 4KiB) called pages.
* Each page can be mapped to physical memory or it can be unmapped(to create virtual memory). * Each page can be mapped to physical memory or it can be unmapped(to create virtual memory).
* Segmentation is a built-in functionality of x86 architecture, so to get around this we need to * Segmentation is a built-in functionality of x86 architecture, so to get around this we need to
* define our own GDT. A cool thing segmentation can do for us is to set Ring Level: * define our own GDT. A cool thing segmentation can do for us is to set Ring Level:
* a privilege level to allow our process to run in a 'unprivileged' mode(called user mode, ring 3) * a privilege level to allow our process to run in a 'unprivileged' mode(called user mode, ring 3)
* and to allow drivers(or kernel related stuff) to run in a 'supervisor-mode'(called kernel mode, ring 0). * and to allow drivers(or kernel related stuff) to run in a 'supervisor-mode'(called kernel mode, ring 0).
* Usually bootloader(such as GRUB) sets up GDT for us, the problem is that we cannot known where it is or * Usually bootloader(such as GRUB) sets up GDT for us, the problem is that we cannot known where it is or
* if it is has been overwritten during some other tasks. So it's a good idea to implement * if it is has been overwritten during some other tasks. So it's a good idea to implement
* a new GDT ourself. * a new GDT ourself.
*/ */
/* Those values were taken from Intel's developer manual */ /* Those values were taken from Intel's developer manual */
// GDT fields // GDT fields
#define GDT_BASE 0x00000000 #define GDT_BASE 0x00000000
#define GDT_LIMIT 0xFFFFFFFF #define GDT_LIMIT 0xFFFFFFFF
// GDT granularity // GDT granularity
#define GDT_SEGMENT_LENGTH 0xF #define GDT_SEGMENT_LENGTH 0xF
#define GDT_OPERAND_SIZE_16 0 #define GDT_OPERAND_SIZE_16 0
#define GDT_OPERAND_SIZE_32 1 #define GDT_OPERAND_SIZE_32 1
#define GDT_GRANULARITY_1K 0 #define GDT_GRANULARITY_1K 0
#define GDT_GRANULARITY_4K 1 #define GDT_GRANULARITY_4K 1
// GDT access type fields // GDT access type fields
#define GDT_DATA_TYPE_READ_ONLY 0x0 #define GDT_DATA_TYPE_READ_ONLY 0x0
#define GDT_DATA_TYPE_READ_ONLY_ACCESSED 0x1 #define GDT_DATA_TYPE_READ_ONLY_ACCESSED 0x1
#define GDT_DATA_TYPE_READ_WRITE 0x2 #define GDT_DATA_TYPE_READ_WRITE 0x2
#define GDT_DATA_TYPE_READ_WRITE_ACCESSED 0x3 #define GDT_DATA_TYPE_READ_WRITE_ACCESSED 0x3
#define GDT_DATA_TYPE_READ_ONLY_EXPAND_DOWN 0x4 #define GDT_DATA_TYPE_READ_ONLY_EXPAND_DOWN 0x4
#define GDT_DATA_TYPE_READ_ONLY_EXPAND_DOWN_ACCESSED 0x5 #define GDT_DATA_TYPE_READ_ONLY_EXPAND_DOWN_ACCESSED 0x5
#define GDT_DATA_TYPE_READ_WRITE_EXPAND_DOWN 0x6 #define GDT_DATA_TYPE_READ_WRITE_EXPAND_DOWN 0x6
#define GDT_DATA_TYPE_READ_WRITE_EXPAND_DOWN_ACCESSED 0x7 #define GDT_DATA_TYPE_READ_WRITE_EXPAND_DOWN_ACCESSED 0x7
#define GDT_DATA_TYPE_EXEC_ONLY 0x8 #define GDT_DATA_TYPE_EXEC_ONLY 0x8
#define GDT_CODE_TYPE_EXEC_ONLY_ACCESSED 0x9 #define GDT_CODE_TYPE_EXEC_ONLY_ACCESSED 0x9
#define GDT_CODE_TYPE_EXEC_READ 0xA #define GDT_CODE_TYPE_EXEC_READ 0xA
#define GDT_CODE_TYPE_EXEC_READ_ACCESSED 0xB #define GDT_CODE_TYPE_EXEC_READ_ACCESSED 0xB
#define GDT_CODE_TYPE_EXEC_CONFORMING 0xC #define GDT_CODE_TYPE_EXEC_CONFORMING 0xC
#define GDT_CODE_TYPE_EXEC_CONFORMING_ACCESSED 0xD #define GDT_CODE_TYPE_EXEC_CONFORMING_ACCESSED 0xD
#define GDT_CODE_TYPE_EXEC_READ_CONFORMING 0xE #define GDT_CODE_TYPE_EXEC_READ_CONFORMING 0xE
#define GDT_CODE_TYPE_EXEC_READ_CONFORMING_ACCESSED 0xF #define GDT_CODE_TYPE_EXEC_READ_CONFORMING_ACCESSED 0xF
// Descriptor type fields // Descriptor type fields
#define GDT_SYSTEM_DESCRIPTOR 0 #define GDT_SYSTEM_DESCRIPTOR 0
#define GDT_CODE_AND_DATA_DESCRIPTOR 1 #define GDT_CODE_AND_DATA_DESCRIPTOR 1
// GDT Ring number // GDT Ring number
#define GDT_RING0 0 #define GDT_RING0 0
#define GDT_RING1 1 #define GDT_RING1 1
#define GDT_RING2 2 #define GDT_RING2 2
#define GDT_RING3 3 #define GDT_RING3 3
// 'Present' field // 'Present' field
#define GDT_SEGMENT_NOT_PRESENT 0 #define GDT_SEGMENT_NOT_PRESENT 0
#define GDT_SEGMENT_PRESENT 1 #define GDT_SEGMENT_PRESENT 1
/* Global Descriptor Table (GDT) implementation */ /* Global Descriptor Table (GDT) implementation */
/* gdt_access is used to access portion of the GDT /* gdt_access is used to access portion of the GDT
* | 0 - 3 | 4 | 3 - 6 | 7 | * | 0 - 3 | 4 | 3 - 6 | 7 |
* | Type | DT | DPL | P | * | Type | DT | DPL | P |
* Type: Which type * Type: Which type
* DT: descriptor type * DT: descriptor type
* DPL: Kernel ring(0-3) * DPL: Kernel ring(0-3)
* P: is segment present? (bool) * P: is segment present? (bool)
*/ */
struct gdt_access { struct gdt_access {
uint8_t type: 4; // 4 Bits uint8_t type: 4; // 4 Bits
uint8_t dt: 1; // 1 Bit uint8_t dt: 1; // 1 Bit
uint8_t dpl: 2; // 2 Bits uint8_t dpl: 2; // 2 Bits
uint8_t p: 1; // 1 Bits uint8_t p: 1; // 1 Bits
}__attribute__((packed)); }__attribute__((packed));
typedef struct gdt_access gdt_access_t; typedef struct gdt_access gdt_access_t;
/* gdt_granularity is used to get portion of GDT entry /* gdt_granularity is used to get portion of GDT entry
* | 0 - 3 | 4 | 5 | 6 | 7 | * | 0 - 3 | 4 | 5 | 6 | 7 |
* | seglen | 0 | D | G | * | seglen | 0 | D | G |
* seglen: segment length * seglen: segment length
* 0: Always zero * 0: Always zero
* D: Operand size (0 = 16 bit, 1 = 32 bit) * D: Operand size (0 = 16 bit, 1 = 32 bit)
* G: granularity (0 = 1 Byte, 1 = 4KiB) * G: granularity (0 = 1 Byte, 1 = 4KiB)
*/ */
struct gdt_granularity { struct gdt_granularity {
uint8_t seglen: 4; uint8_t seglen: 4;
uint8_t zero: 2; uint8_t zero: 2;
uint8_t d: 1; uint8_t d: 1;
uint8_t g: 1; uint8_t g: 1;
}__attribute__((packed)); }__attribute__((packed));
typedef struct gdt_granularity gdt_gran_t; typedef struct gdt_granularity gdt_gran_t;
/* gdt_entry_struct contains the value of a single GDT entry /* gdt_entry_struct contains the value of a single GDT entry
* Each slice is 64 bits. * Each slice is 64 bits.
* | 0 - 15 | 16 - 31 | 32 - 39 | 40 - 47 | 48 - 55 | 56 - 63 | * | 0 - 15 | 16 - 31 | 32 - 39 | 40 - 47 | 48 - 55 | 56 - 63 |
* | lim low| base low|base mid | access | gran | base hg | * | lim low| base low|base mid | access | gran | base hg |
* lim low: Lower 16 bits of the limit * lim low: Lower 16 bits of the limit
* base low: Lower 16 bits of the base * base low: Lower 16 bits of the base
* base mid: Next 8 bits of the base * base mid: Next 8 bits of the base
* access: access flag, e.g. which ring this segment can be used in. * access: access flag, e.g. which ring this segment can be used in.
* gran. * gran.
*/ */
struct gdt_entry_struct { struct gdt_entry_struct {
uint16_t limit_low; uint16_t limit_low;
uint16_t base_low; uint16_t base_low;
uint8_t base_middle; uint8_t base_middle;
gdt_access_t access; gdt_access_t access;
gdt_gran_t granularity; gdt_gran_t granularity;
uint8_t base_high; uint8_t base_high;
}__attribute__((packed)); }__attribute__((packed));
typedef struct gdt_entry_struct gdt_entry_t; typedef struct gdt_entry_struct gdt_entry_t;
/* Also we have to define a pointer to the data structure /* Also we have to define a pointer to the data structure
* This is needed to locate it later */ * This is needed to locate it later */
struct gdt_ptr { struct gdt_ptr {
uint16_t limit; uint16_t limit;
uint32_t base; uint32_t base;
}__attribute__((packed)); }__attribute__((packed));
typedef struct gdt_ptr gdt_ptr_t; typedef struct gdt_ptr gdt_ptr_t;
/* GDT Kernel API */ /* GDT Kernel API */
void gdt_setup(); void gdt_setup();
#endif #endif

View File

@ -1,122 +1,122 @@
#include "idt.h" #include "idt.h"
#include "../libc/string.h" #include "../libc/string.h"
#include "ports.h" #include "ports.h"
// Internal method // Internal method
extern void idt_flush(idt_ptr_t*); // defined on cpu/idt.asm extern void idt_flush(idt_ptr_t*); // defined on cpu/idt.asm
static void init_idt(); static void init_idt();
static void idt_set_gate(uint8_t idx, void(*base), uint16_t selector, idt_flags_t flags); static void idt_set_gate(uint8_t idx, void(*base), uint16_t selector, idt_flags_t flags);
static void pic_remap(uint8_t offset1, uint8_t offset2); static void pic_remap(uint8_t offset1, uint8_t offset2);
idt_entry_t idt_entries[256]; // 256 interrupts idt_entry_t idt_entries[256]; // 256 interrupts
idt_ptr_t idt_ptr; idt_ptr_t idt_ptr;
// This method will be called by the kernel // This method will be called by the kernel
void idt_setup() { void idt_setup() {
init_idt(); init_idt();
} }
static void idt_set_gate(uint8_t idx, void(*base), uint16_t selector, idt_flags_t flags) { static void idt_set_gate(uint8_t idx, void(*base), uint16_t selector, idt_flags_t flags) {
idt_entries[idx] = (struct idt_entry) { idt_entries[idx] = (struct idt_entry) {
.base_low = (uint32_t)base & 0xFFFF, .base_low = (uint32_t)base & 0xFFFF,
.base_high = ((uint32_t)base >> 16) & 0xFFFF, .base_high = ((uint32_t)base >> 16) & 0xFFFF,
.seg_sel = selector, .seg_sel = selector,
.flags = flags .flags = flags
}; };
} }
static void init_idt() { static void init_idt() {
idt_ptr.limit = sizeof(idt_entry_t) * 256 - 1; idt_ptr.limit = sizeof(idt_entry_t) * 256 - 1;
idt_ptr.base = idt_entries; idt_ptr.base = idt_entries;
memset(&idt_entries, 0, sizeof(idt_entry_t) * 256); memset(&idt_entries, 0, sizeof(idt_entry_t) * 256);
idt_flags_t flags = { idt_flags_t flags = {
.reserved = IDT_FLAG_RESERVED, // Always 0x0E .reserved = IDT_FLAG_RESERVED, // Always 0x0E
.dpl = 0, .dpl = 0,
.p = 1 .p = 1
}; };
// Remap IDT with ISRs // Remap IDT with ISRs
idt_set_gate(0, isr0, 0x08, flags); idt_set_gate(0, isr0, 0x08, flags);
idt_set_gate(1, isr1, 0x08, flags); idt_set_gate(1, isr1, 0x08, flags);
idt_set_gate(2, isr2, 0x08, flags); idt_set_gate(2, isr2, 0x08, flags);
idt_set_gate(3, isr3, 0x08, flags); idt_set_gate(3, isr3, 0x08, flags);
idt_set_gate(4, isr4, 0x08, flags); idt_set_gate(4, isr4, 0x08, flags);
idt_set_gate(5, isr5, 0x08, flags); idt_set_gate(5, isr5, 0x08, flags);
idt_set_gate(6, isr6, 0x08, flags); idt_set_gate(6, isr6, 0x08, flags);
idt_set_gate(7, isr7, 0x08, flags); idt_set_gate(7, isr7, 0x08, flags);
idt_set_gate(8, isr8, 0x08, flags); idt_set_gate(8, isr8, 0x08, flags);
idt_set_gate(9, isr9, 0x08, flags); idt_set_gate(9, isr9, 0x08, flags);
idt_set_gate(10, isr10, 0x08, flags); idt_set_gate(10, isr10, 0x08, flags);
idt_set_gate(11, isr11, 0x08, flags); idt_set_gate(11, isr11, 0x08, flags);
idt_set_gate(12, isr12, 0x08, flags); idt_set_gate(12, isr12, 0x08, flags);
idt_set_gate(13, isr13, 0x08, flags); idt_set_gate(13, isr13, 0x08, flags);
idt_set_gate(14, isr14, 0x08, flags); idt_set_gate(14, isr14, 0x08, flags);
idt_set_gate(15, isr15, 0x08, flags); idt_set_gate(15, isr15, 0x08, flags);
idt_set_gate(16, isr16, 0x08, flags); idt_set_gate(16, isr16, 0x08, flags);
idt_set_gate(17, isr17, 0x08, flags); idt_set_gate(17, isr17, 0x08, flags);
idt_set_gate(18, isr18, 0x08, flags); idt_set_gate(18, isr18, 0x08, flags);
idt_set_gate(19, isr19, 0x08, flags); idt_set_gate(19, isr19, 0x08, flags);
idt_set_gate(20, isr20, 0x08, flags); idt_set_gate(20, isr20, 0x08, flags);
idt_set_gate(21, isr21, 0x08, flags); idt_set_gate(21, isr21, 0x08, flags);
idt_set_gate(22, isr22, 0x08, flags); idt_set_gate(22, isr22, 0x08, flags);
idt_set_gate(23, isr23, 0x08, flags); idt_set_gate(23, isr23, 0x08, flags);
idt_set_gate(24, isr24, 0x08, flags); idt_set_gate(24, isr24, 0x08, flags);
idt_set_gate(25, isr25, 0x08, flags); idt_set_gate(25, isr25, 0x08, flags);
idt_set_gate(26, isr26, 0x08, flags); idt_set_gate(26, isr26, 0x08, flags);
idt_set_gate(27, isr27, 0x08, flags); idt_set_gate(27, isr27, 0x08, flags);
idt_set_gate(28, isr28, 0x08, flags); idt_set_gate(28, isr28, 0x08, flags);
idt_set_gate(29, isr29, 0x08, flags); idt_set_gate(29, isr29, 0x08, flags);
idt_set_gate(30, isr30, 0x08, flags); idt_set_gate(30, isr30, 0x08, flags);
idt_set_gate(31, isr31, 0x08, flags); idt_set_gate(31, isr31, 0x08, flags);
// Remap PIC // Remap PIC
pic_remap(PIC1_START_INTERRUPT, PIC2_START_INTERRUPT); pic_remap(PIC1_START_INTERRUPT, PIC2_START_INTERRUPT);
// Also remap 15 entries for IRQs // Also remap 15 entries for IRQs
idt_set_gate(32, irq0, 0x08, flags); idt_set_gate(32, irq0, 0x08, flags);
idt_set_gate(33, irq1, 0x08, flags); idt_set_gate(33, irq1, 0x08, flags);
idt_set_gate(34, irq2, 0x08, flags); idt_set_gate(34, irq2, 0x08, flags);
idt_set_gate(35, irq3, 0x08, flags); idt_set_gate(35, irq3, 0x08, flags);
idt_set_gate(36, irq4, 0x08, flags); idt_set_gate(36, irq4, 0x08, flags);
idt_set_gate(37, irq5, 0x08, flags); idt_set_gate(37, irq5, 0x08, flags);
idt_set_gate(38, irq6, 0x08, flags); idt_set_gate(38, irq6, 0x08, flags);
idt_set_gate(39, irq7, 0x08, flags); idt_set_gate(39, irq7, 0x08, flags);
idt_set_gate(40, irq8, 0x08, flags); idt_set_gate(40, irq8, 0x08, flags);
idt_set_gate(41, irq9, 0x08, flags); idt_set_gate(41, irq9, 0x08, flags);
idt_set_gate(42, irq10, 0x08, flags); idt_set_gate(42, irq10, 0x08, flags);
idt_set_gate(43, irq11, 0x08, flags); idt_set_gate(43, irq11, 0x08, flags);
idt_set_gate(44, irq12, 0x08, flags); idt_set_gate(44, irq12, 0x08, flags);
idt_set_gate(45, irq13, 0x08, flags); idt_set_gate(45, irq13, 0x08, flags);
idt_set_gate(46, irq14, 0x08, flags); idt_set_gate(46, irq14, 0x08, flags);
idt_set_gate(47, irq15, 0x08, flags); idt_set_gate(47, irq15, 0x08, flags);
idt_flush(&idt_ptr); idt_flush(&idt_ptr);
// Finally enable hardware interrupts with an assembly instruction // Finally enable hardware interrupts with an assembly instruction
__asm__ __volatile__ ("sti"); __asm__ __volatile__ ("sti");
} }
// Taken from: http://wiki.osdev.org/8259_PIC // Taken from: http://wiki.osdev.org/8259_PIC
static void pic_remap(uint8_t offset1, uint8_t offset2) { static void pic_remap(uint8_t offset1, uint8_t offset2) {
uint8_t a1, a2; uint8_t a1, a2;
a1 = inb(PIC1_DATA); // Save masks a1 = inb(PIC1_DATA); // Save masks
a2 = inb(PIC2_DATA); a2 = inb(PIC2_DATA);
outb(PIC1_COMMAND, ICW1_INIT+ICW1_ICW4); // Start init sequence outb(PIC1_COMMAND, ICW1_INIT+ICW1_ICW4); // Start init sequence
outb(PIC2_COMMAND, ICW1_INIT+ICW1_ICW4); outb(PIC2_COMMAND, ICW1_INIT+ICW1_ICW4);
outb(PIC1_DATA, offset1); outb(PIC1_DATA, offset1);
outb(PIC2_DATA, offset2); outb(PIC2_DATA, offset2);
outb(PIC1_DATA, 4); // Tell master PIC that there is a slave PIC at IRQ2 outb(PIC1_DATA, 4); // Tell master PIC that there is a slave PIC at IRQ2
outb(PIC1_DATA, 2); // Tell salve PIC it's cascade identity outb(PIC1_DATA, 2); // Tell salve PIC it's cascade identity
outb(PIC1_DATA, ICW4_8086); outb(PIC1_DATA, ICW4_8086);
outb(PIC2_DATA, ICW4_8086); outb(PIC2_DATA, ICW4_8086);
// Restore saved masks // Restore saved masks
outb(PIC1_DATA, a1); outb(PIC1_DATA, a1);
outb(PIC2_DATA, a2); outb(PIC2_DATA, a2);
} }

View File

@ -1,144 +1,144 @@
/************************************** /*****************************************
* VulcanOS Kernel * * VulcanOS Kernel *
* Developed by Marco 'icebit' Cetica * * Developed by Marco 'icebit' Cetica *
* (c) 2019-2021 * * (c) 2019-2021 *
* Released under GPLv3 * * Released under GPLv3 *
* https://github.com/ice-bit/iceOS * * https://github.com/ice-bit/vulcanos *
***************************************/ *****************************************/
#ifndef _IDT_H_ #ifndef _IDT_H_
#define _IDT_H_ #define _IDT_H_
#include <stdint.h> #include <stdint.h>
/* /*
* First a bit of theory: * First a bit of theory:
* Sometimes you want to interrupt the processor from what it is currently doing * Sometimes you want to interrupt the processor from what it is currently doing
* and force it to do something more "critical", such as a timer update or a keyboard interrupt * and force it to do something more "critical", such as a timer update or a keyboard interrupt
* request(IRQ) fires. The processor, then, will handle those IRQs activating an * request(IRQ) fires. The processor, then, will handle those IRQs activating an
* interrupt handler(ISR, Interrupt Service Routines). In order to know where to find those * interrupt handler(ISR, Interrupt Service Routines). In order to know where to find those
* ISRs, the CPU will use the IDT. So we can say that the Interrupt Description Table * ISRs, the CPU will use the IDT. So we can say that the Interrupt Description Table
* is another data structure(organized the same way as the GDT) that will provide a list * is another data structure(organized the same way as the GDT) that will provide a list
* of interrupts handlers(ISRs) to the CPU. * of interrupts handlers(ISRs) to the CPU.
*/ */
// Reserved bits in IDT entries // Reserved bits in IDT entries
#define IDT_FLAG_RESERVED 0x0E #define IDT_FLAG_RESERVED 0x0E
// PIC // PIC
#define PIC1 0x20 // I/O address for master PIC #define PIC1 0x20 // I/O address for master PIC
#define PIC2 0xA0 // I/O address for slave PIC #define PIC2 0xA0 // I/O address for slave PIC
#define PIC1_COMMAND PIC1 #define PIC1_COMMAND PIC1
#define PIC1_DATA (PIC1+1) #define PIC1_DATA (PIC1+1)
#define PIC2_COMMAND PIC2 #define PIC2_COMMAND PIC2
#define PIC2_DATA (PIC2+1) #define PIC2_DATA (PIC2+1)
#define PIC1_START_INTERRUPT 0x20 // Master PIC after remapping #define PIC1_START_INTERRUPT 0x20 // Master PIC after remapping
#define PIC2_START_INTERRUPT 0x28 // Slave PIC after remapping #define PIC2_START_INTERRUPT 0x28 // Slave PIC after remapping
#define PIC_EOI 0x20 // End of interrupt #define PIC_EOI 0x20 // End of interrupt
#define ICW1_ICW4 0x01 #define ICW1_ICW4 0x01
#define ICW1_SINGLE 0x02 #define ICW1_SINGLE 0x02
#define ICW1_INTERVAL4 0x04 #define ICW1_INTERVAL4 0x04
#define ICW1_LEVEL 0x08 #define ICW1_LEVEL 0x08
#define ICW1_INIT 0x10 #define ICW1_INIT 0x10
#define ICW4_8086 0x01 // 8086/88 (MCS-80/85) mode #define ICW4_8086 0x01 // 8086/88 (MCS-80/85) mode
#define ICW4_AUTO 0x02 #define ICW4_AUTO 0x02
#define ICW4_BUF_SLAVE 0x08 #define ICW4_BUF_SLAVE 0x08
#define ICW4_BUF_MASTER 0x0C #define ICW4_BUF_MASTER 0x0C
#define ICW4_SFNM 0x10 #define ICW4_SFNM 0x10
/* Interrupt Descriptor Table */ /* Interrupt Descriptor Table */
/* idt_flags contains access flag of a single IDT entry /* idt_flags contains access flag of a single IDT entry
* | 0 - 4 | 5 - 6 | 7 | * | 0 - 4 | 5 - 6 | 7 |
* | res | dpl | p | * | res | dpl | p |
* res: always 0x0E * res: always 0x0E
* dpl: ring num (0 - 3) * dpl: ring num (0 - 3)
* p: segment present (bool) * p: segment present (bool)
*/ */
struct idt_flags { struct idt_flags {
uint8_t reserved: 5; uint8_t reserved: 5;
uint8_t dpl: 2; uint8_t dpl: 2;
uint8_t p: 1; uint8_t p: 1;
}__attribute__((packed)); }__attribute__((packed));
typedef struct idt_flags idt_flags_t; typedef struct idt_flags idt_flags_t;
/* idt_entry contains the value of an IDT entry /* idt_entry contains the value of an IDT entry
* Each entry is 64 bits(like GDT entry) * Each entry is 64 bits(like GDT entry)
* | 0 - 15 | 16 - 31 | 32 - 39 | 40 - 47 | 48 - 63 | * | 0 - 15 | 16 - 31 | 32 - 39 | 40 - 47 | 48 - 63 |
* | b low | seg sel | res | flags | b high | * | b low | seg sel | res | flags | b high |
* b low: Lower 16 bits of the base * b low: Lower 16 bits of the base
* seg sel: Segment selector for code segment * seg sel: Segment selector for code segment
* res: always 0 * res: always 0
* flags: idt_flags struct * flags: idt_flags struct
* b high: Higher 16 bits of the base * b high: Higher 16 bits of the base
*/ */
struct idt_entry { struct idt_entry {
uint16_t base_low; uint16_t base_low;
uint16_t seg_sel; uint16_t seg_sel;
uint8_t reserved; uint8_t reserved;
idt_flags_t flags; idt_flags_t flags;
uint16_t base_high; uint16_t base_high;
}__attribute__((packed)); }__attribute__((packed));
typedef struct idt_entry idt_entry_t; typedef struct idt_entry idt_entry_t;
/* Also we have to define a pointer to the data structure /* Also we have to define a pointer to the data structure
* This is needed to locate it later */ * This is needed to locate it later */
struct idt_ptr { struct idt_ptr {
uint16_t limit; uint16_t limit;
idt_entry_t *base; idt_entry_t *base;
}__attribute__((packed)); }__attribute__((packed));
typedef struct idt_ptr idt_ptr_t; typedef struct idt_ptr idt_ptr_t;
/* IDT Kernel API */ /* IDT Kernel API */
void idt_setup(); void idt_setup();
// ISRs method declaration // ISRs method declaration
extern void isr0(); extern void isr0();
extern void isr1(); extern void isr1();
extern void isr2(); extern void isr2();
extern void isr3(); extern void isr3();
extern void isr4(); extern void isr4();
extern void isr5(); extern void isr5();
extern void isr6(); extern void isr6();
extern void isr7(); extern void isr7();
extern void isr8(); extern void isr8();
extern void isr9(); extern void isr9();
extern void isr10(); extern void isr10();
extern void isr11(); extern void isr11();
extern void isr12(); extern void isr12();
extern void isr13(); extern void isr13();
extern void isr14(); extern void isr14();
extern void isr15(); extern void isr15();
extern void isr16(); extern void isr16();
extern void isr17(); extern void isr17();
extern void isr18(); extern void isr18();
extern void isr19(); extern void isr19();
extern void isr20(); extern void isr20();
extern void isr21(); extern void isr21();
extern void isr22(); extern void isr22();
extern void isr23(); extern void isr23();
extern void isr24(); extern void isr24();
extern void isr25(); extern void isr25();
extern void isr26(); extern void isr26();
extern void isr27(); extern void isr27();
extern void isr28(); extern void isr28();
extern void isr29(); extern void isr29();
extern void isr30(); extern void isr30();
extern void isr31(); extern void isr31();
extern void irq0(); extern void irq0();
extern void irq1(); extern void irq1();
extern void irq2(); extern void irq2();
extern void irq3(); extern void irq3();
extern void irq4(); extern void irq4();
extern void irq5(); extern void irq5();
extern void irq6(); extern void irq6();
extern void irq7(); extern void irq7();
extern void irq8(); extern void irq8();
extern void irq9(); extern void irq9();
extern void irq10(); extern void irq10();
extern void irq11(); extern void irq11();
extern void irq12(); extern void irq12();
extern void irq13(); extern void irq13();
extern void irq14(); extern void irq14();
extern void irq15(); extern void irq15();
#endif #endif

View File

@ -1,56 +1,56 @@
#include "initrd.h" #include "initrd.h"
// Declare various things // Declare various things
initrd_header_t *initrd_header; // Header initrd_header_t *initrd_header; // Header
initrd_file_header_t *file_header; // List of headers initrd_file_header_t *file_header; // List of headers
fs_node_t *initrd_root; // Directory root node fs_node_t *initrd_root; // Directory root node
fs_node_t *initrd_dev; // Directory dev node(/dev) fs_node_t *initrd_dev; // Directory dev node(/dev)
fs_node_t *root_nodes; // List of file nodes fs_node_t *root_nodes; // List of file nodes
uint32_t nroot_nodes; uint32_t nroot_nodes;
struct dirent dirent; struct dirent dirent;
fs_node_t *init_ramdisk(uint32_t multiboot_location) { fs_node_t *init_ramdisk(uint32_t multiboot_location) {
// Initialize main and file headers // Initialize main and file headers
initrd_header = (initrd_header_t*)multiboot_location; initrd_header = (initrd_header_t*)multiboot_location;
file_header = (initrd_file_header_t*)(multiboot_location+sizeof(initrd_header_t)); file_header = (initrd_file_header_t*)(multiboot_location+sizeof(initrd_header_t));
// Initialize root directory // Initialize root directory
initrd_root = (fs_node_t*) initrd_root = (fs_node_t*)
} }
static uint32_t initrd_read(fs_node_t *node, uint32_t offset, uint32_t size, uint8_t *buffer) { static uint32_t initrd_read(fs_node_t *node, uint32_t offset, uint32_t size, uint8_t *buffer) {
initrd_file_header_t header = file_header[node->inode]; initrd_file_header_t header = file_header[node->inode];
if(offset > header.length) if(offset > header.length)
return 0; return 0;
if(offset+size > header.length) if(offset+size > header.length)
size = header.length-offset; size = header.length-offset;
memcpy(buffer, (uint8_t*) (header.offset+offset), size); memcpy(buffer, (uint8_t*) (header.offset+offset), size);
return size; return size;
} }
static struct dirent *initrd_readdir(fs_node_t *node, uint32_t index) { static struct dirent *initrd_readdir(fs_node_t *node, uint32_t index) {
if(node == initrd_root && index == 0) { if(node == initrd_root && index == 0) {
strcpy(dirent.name, "dev"); strcpy(dirent.name, "dev");
dirent.name[3] = 0; // Add null terminator to the string dirent.name[3] = 0; // Add null terminator to the string
dirent.ino = 0; dirent.ino = 0;
return &dirent; return &dirent;
} }
if(index-1 >= &root_nodes) if(index-1 >= &root_nodes)
return 0; return 0;
strcpy(dirent.name, root_nodes[index-1].name); strcpy(dirent.name, root_nodes[index-1].name);
dirent.name[strlen(root_nodes[index-1].name)] = 0; // Add null terminator dirent.name[strlen(root_nodes[index-1].name)] = 0; // Add null terminator
dirent.ino = root_nodes[index-1].inode; dirent.ino = root_nodes[index-1].inode;
return &dirent; return &dirent;
} }
static fs_node_t *initrd_finddir(fs_node_t *node, uint8_t *name) { static fs_node_t *initrd_finddir(fs_node_t *node, uint8_t *name) {
if(node == initrd_root && !strcmp(name, "dev")) if(node == initrd_root && !strcmp(name, "dev"))
return initrd_dev; return initrd_dev;
for(uint32_t i = 0; i < nroot_nodes; i++) for(uint32_t i = 0; i < nroot_nodes; i++)
if(!strcmp(name, root_nodes[i].name)) if(!strcmp(name, root_nodes[i].name))
return &root_nodes[i]; return &root_nodes[i];
return 0; return 0;
} }

View File

@ -1,36 +1,36 @@
/************************************** /*****************************************
* VulcanOS Kernel * * VulcanOS Kernel *
* Developed by Marco 'icebit' Cetica * * Developed by Marco 'icebit' Cetica *
* (c) 2019-2021 * * (c) 2019-2021 *
* Released under GPLv3 * * Released under GPLv3 *
* https://github.com/ice-bit/iceOS * * https://github.com/ice-bit/vulcanos *
***************************************/ *****************************************/
#ifndef INITRD_H #ifndef INITRD_H
#define INITRD_H #define INITRD_H
/* Ramdisk is a file system that is loaded along with the kernel /* Ramdisk is a file system that is loaded along with the kernel
* and it usually contains configuration files or file system drivers. * and it usually contains configuration files or file system drivers.
* It is used BEFORE partitions are being mounted*/ * It is used BEFORE partitions are being mounted*/
#include <stdint.h> #include <stdint.h>
#include "../libc/string.h" #include "../libc/string.h"
#include "fs.h" #include "fs.h"
typedef struct { typedef struct {
uint32_t nfiles; // Number of files in the ramdisk uint32_t nfiles; // Number of files in the ramdisk
} initrd_header_t; } initrd_header_t;
typedef struct { typedef struct {
uint8_t magic; // Magic number for error checking uint8_t magic; // Magic number for error checking
int8_t name[64]; // Filename int8_t name[64]; // Filename
uint32_t offset; uint32_t offset;
uint32_t length; // Length of the file uint32_t length; // Length of the file
} initrd_file_header_t; } initrd_file_header_t;
// Function to initialize initrd, we'll pass the multiboot // Function to initialize initrd, we'll pass the multiboot
// module as parameter // module as parameter
fs_node_t *init_ramdisk(uint32_t multiboot_location); fs_node_t *init_ramdisk(uint32_t multiboot_location);
static uint32_t initrd_read(fs_node_t *node, uint32_t offset, uint32_t size, uint8_t *buffer); static uint32_t initrd_read(fs_node_t *node, uint32_t offset, uint32_t size, uint8_t *buffer);
static struct dirent *initrd_readdir(fs_node_t *node, uint32_t index); static struct dirent *initrd_readdir(fs_node_t *node, uint32_t index);
static fs_node_t *initrd_finddir(fs_node_t *node, uint8_t *name); static fs_node_t *initrd_finddir(fs_node_t *node, uint8_t *name);
#endif #endif

View File

@ -1,87 +1,87 @@
#include <stdint.h> #include <stdint.h>
#include "isr.h" #include "isr.h"
#include "tty.h" #include "tty.h"
#include "../libc/string.h" #include "../libc/string.h"
#include "ports.h" #include "ports.h"
#define PIC1 0x20 // I/O address for master PIC #define PIC1 0x20 // I/O address for master PIC
#define PIC2 0xA0 // I/O address for slave PIC #define PIC2 0xA0 // I/O address for slave PIC
#define PIC1_COMMAND PIC1 #define PIC1_COMMAND PIC1
#define PIC1_DATA (PIC1+1) #define PIC1_DATA (PIC1+1)
#define PIC2_COMMAND PIC2 #define PIC2_COMMAND PIC2
#define PIC2_DATA (PIC2+1) #define PIC2_DATA (PIC2+1)
#define PIC_EOI 0x20 // End Of Interrupt command #define PIC_EOI 0x20 // End Of Interrupt command
// List of messages for known interrupts // List of messages for known interrupts
uint8_t *interrupts_messages[] = { uint8_t *interrupts_messages[] = {
(uint8_t*)"Division by Zero", // 0 (uint8_t*)"Division by Zero", // 0
(uint8_t*)"Debug", (uint8_t*)"Debug",
(uint8_t*)"Non-maskable interrupt", (uint8_t*)"Non-maskable interrupt",
(uint8_t*)"Breakpoint", (uint8_t*)"Breakpoint",
(uint8_t*)"Detected overflow", (uint8_t*)"Detected overflow",
(uint8_t*)"Out-of-bounds", // 5 (uint8_t*)"Out-of-bounds", // 5
(uint8_t*)"Invalid opcode", (uint8_t*)"Invalid opcode",
(uint8_t*)"No coprocessor", (uint8_t*)"No coprocessor",
(uint8_t*)"Double fault", (uint8_t*)"Double fault",
(uint8_t*)"Coprocessor segment overrun", (uint8_t*)"Coprocessor segment overrun",
(uint8_t*)"Bad TSS", // 10 (uint8_t*)"Bad TSS", // 10
(uint8_t*)"Segment not present", (uint8_t*)"Segment not present",
(uint8_t*)"Stack fault", (uint8_t*)"Stack fault",
(uint8_t*)"General protection fault", (uint8_t*)"General protection fault",
(uint8_t*)"Page fault", (uint8_t*)"Page fault",
(uint8_t*)"Unknown interrupt", // 15 (uint8_t*)"Unknown interrupt", // 15
(uint8_t*)"Coprocessor fault", (uint8_t*)"Coprocessor fault",
(uint8_t*)"Alignment check", (uint8_t*)"Alignment check",
(uint8_t*)"Machine check", (uint8_t*)"Machine check",
(uint8_t*)"Reserved", (uint8_t*)"Reserved",
(uint8_t*)"Reserved", (uint8_t*)"Reserved",
(uint8_t*)"Reserved", (uint8_t*)"Reserved",
(uint8_t*)"Reserved", (uint8_t*)"Reserved",
(uint8_t*)"Reserved", (uint8_t*)"Reserved",
(uint8_t*)"Reserved", (uint8_t*)"Reserved",
(uint8_t*)"Reserved", (uint8_t*)"Reserved",
(uint8_t*)"Reserved", (uint8_t*)"Reserved",
(uint8_t*)"Reserved", (uint8_t*)"Reserved",
(uint8_t*)"Reserved", (uint8_t*)"Reserved",
(uint8_t*)"Reserved", (uint8_t*)"Reserved",
(uint8_t*)"Reserved", (uint8_t*)"Reserved",
(uint8_t*)"Reserved" (uint8_t*)"Reserved"
}; };
isr_t interrupt_handler[256]; isr_t interrupt_handler[256];
void isr_handler(registers_t regs) { void isr_handler(registers_t regs) {
if(interrupt_handler[regs.int_num] != 0) { if(interrupt_handler[regs.int_num] != 0) {
isr_t handler = interrupt_handler[regs.int_num]; isr_t handler = interrupt_handler[regs.int_num];
handler(regs); handler(regs);
} else { } else {
uint8_t *buf = (uint8_t*)"\nReceived interrupt: "; uint8_t *buf = (uint8_t*)"\nReceived interrupt: ";
kprint_c((uint8_t*)buf,strlen(buf), LIGHT_BROWN, BLACK); kprint_c((uint8_t*)buf,strlen(buf), LIGHT_BROWN, BLACK);
kprint_c(interrupts_messages[(uint8_t)regs.int_num], kprint_c(interrupts_messages[(uint8_t)regs.int_num],
strlen(interrupts_messages[(uint8_t)regs.int_num]), strlen(interrupts_messages[(uint8_t)regs.int_num]),
WHITE, WHITE,
BLACK BLACK
); );
} }
} }
void ack_irq(uint32_t int_num) { void ack_irq(uint32_t int_num) {
// Send and End Of Interrupt(EOF) at the PICs. // Send and End Of Interrupt(EOF) at the PICs.
if(int_num >= 40) if(int_num >= 40)
outb(PIC2_COMMAND, PIC_EOI); // Send reset signal to slave outb(PIC2_COMMAND, PIC_EOI); // Send reset signal to slave
outb(PIC1_COMMAND, PIC_EOI); // In any case, reset the master outb(PIC1_COMMAND, PIC_EOI); // In any case, reset the master
} }
void irq_handler(registers_t regs) { void irq_handler(registers_t regs) {
ack_irq(regs.int_num); ack_irq(regs.int_num);
if(interrupt_handler[regs.int_num] != 0) { if(interrupt_handler[regs.int_num] != 0) {
isr_t handler = interrupt_handler[regs.int_num]; isr_t handler = interrupt_handler[regs.int_num];
handler(regs); handler(regs);
} }
} }
void register_interrupt_handler(uint8_t n, isr_t handler) { void register_interrupt_handler(uint8_t n, isr_t handler) {
interrupt_handler[n] = handler; interrupt_handler[n] = handler;
} }

View File

@ -1,72 +1,72 @@
/************************************** /*****************************************
* VulcanOS Kernel * * VulcanOS Kernel *
* Developed by Marco 'icebit' Cetica * * Developed by Marco 'icebit' Cetica *
* (c) 2019-2021 * * (c) 2019-2021 *
* Released under GPLv3 * * Released under GPLv3 *
* https://github.com/ice-bit/iceOS * * https://github.com/ice-bit/vulcanos *
***************************************/ *****************************************/
#ifndef _ISR_H_ #ifndef _ISR_H_
#define _ISR_H_ #define _ISR_H_
#include <stdint.h> #include <stdint.h>
/* /*
* When we implement ISRs we have to keep in mind that the first 32 interrupts(and so the * When we implement ISRs we have to keep in mind that the first 32 interrupts(and so the
* first 32 ISRs) are reserved by the CPU to signal the kernel about critical actions, * first 32 ISRs) are reserved by the CPU to signal the kernel about critical actions,
* such as divide-by-zero or a stack overflow/buffer overflow. * such as divide-by-zero or a stack overflow/buffer overflow.
* *
* Below ther's a list of the first, reserved, interrupts...and yeah, we have to implement * Below ther's a list of the first, reserved, interrupts...and yeah, we have to implement
* all of them by ourself(btw in Assembly) :D * all of them by ourself(btw in Assembly) :D
* *
* 0 - Division by zero exception * 0 - Division by zero exception
* 1 - Debug exception * 1 - Debug exception
* 2 - Non maskable interrupt * 2 - Non maskable interrupt
* 3 - Breakpoint exception * 3 - Breakpoint exception
* 4 - Into detected overflow * 4 - Into detected overflow
* 5 - Out of bounds exception * 5 - Out of bounds exception
* 6 - Invalid opcode exception * 6 - Invalid opcode exception
* 7 - No coprocessor exception * 7 - No coprocessor exception
* 8 - Double fault (pushes an error code) * 8 - Double fault (pushes an error code)
* 9 - Coprocessor segment overrun * 9 - Coprocessor segment overrun
* 10 - Bad TSS (pushes an error code) * 10 - Bad TSS (pushes an error code)
* 11 - Segment not present (pushes an error code) * 11 - Segment not present (pushes an error code)
* 12 - Stack fault (pushes an error code) * 12 - Stack fault (pushes an error code)
* 13 - General protection fault (pushes an error code) * 13 - General protection fault (pushes an error code)
* 14 - Page fault (pushes an error code) * 14 - Page fault (pushes an error code)
* 15 - Unknown interrupt exception * 15 - Unknown interrupt exception
* 16 - Coprocessor fault * 16 - Coprocessor fault
* 17 - Alignment check exception * 17 - Alignment check exception
* 18 - Machine check exception * 18 - Machine check exception
* 19-31 - Reserved */ * 19-31 - Reserved */
#define IRQ0 32 #define IRQ0 32
#define IRQ1 33 #define IRQ1 33
#define IRQ2 34 #define IRQ2 34
#define IRQ3 35 #define IRQ3 35
#define IRQ4 36 #define IRQ4 36
#define IRQ5 37 #define IRQ5 37
#define IRQ6 38 #define IRQ6 38
#define IRQ7 39 #define IRQ7 39
#define IRQ8 40 #define IRQ8 40
#define IRQ9 41 #define IRQ9 41
#define IRQ10 42 #define IRQ10 42
#define IRQ11 43 #define IRQ11 43
#define IRQ12 44 #define IRQ12 44
#define IRQ13 45 #define IRQ13 45
#define IRQ14 46 #define IRQ14 46
#define IRQ15 47 #define IRQ15 47
typedef struct registers { typedef struct registers {
uint32_t ds; // Data segment uint32_t ds; // Data segment
uint32_t edi, esi, ebp, esp, ebx, edx, ecx, eax; // Pushed with pusha uint32_t edi, esi, ebp, esp, ebx, edx, ecx, eax; // Pushed with pusha
uint32_t int_num, err_code; // Interrupt number and error code uint32_t int_num, err_code; // Interrupt number and error code
uint32_t eip, cs, eflags, usereap, ss; // Pushed by CPU uint32_t eip, cs, eflags, usereap, ss; // Pushed by CPU
} registers_t; } registers_t;
typedef void (*isr_t)(registers_t); typedef void (*isr_t)(registers_t);
void ack_irq(uint32_t int_num); void ack_irq(uint32_t int_num);
void register_interrupt_handler(uint8_t n, isr_t handler); void register_interrupt_handler(uint8_t n, isr_t handler);
#endif #endif

View File

@ -1,118 +1,118 @@
/* The keyboard driver works with a device called PS/2: to talk with this /* The keyboard driver works with a device called PS/2: to talk with this
* controller we can use serial communication(e.g. ports.h). The actual flow of * controller we can use serial communication(e.g. ports.h). The actual flow of
* data is made with "commands", each command is one byte and the keyboard's * data is made with "commands", each command is one byte and the keyboard's
* controller can send two type of response: * controller can send two type of response:
* ACK(Acknowledge): to acknowledge the previous command * ACK(Acknowledge): to acknowledge the previous command
* Resend: to resend the previous command due to an error. * Resend: to resend the previous command due to an error.
* We have also to wait between the command, the data and the response of * We have also to wait between the command, the data and the response of
* the PS/2 controller. * the PS/2 controller.
* This device should not exists anymore in any modern computer * This device should not exists anymore in any modern computer
* motherboard; however the CPU(or the motherboard?) should be able to * motherboard; however the CPU(or the motherboard?) should be able to
* simulate it even if we're using some USB keyboard. * simulate it even if we're using some USB keyboard.
* Apart of that the keyboard will be listen on IRQ1(33), * Apart of that the keyboard will be listen on IRQ1(33),
* so we have to register an ISR for that. * so we have to register an ISR for that.
*/ */
#include "keyboard.h" #include "keyboard.h"
#include "isr.h" #include "isr.h"
#include "ports.h" #include "ports.h"
#include "tty.h" #include "tty.h"
#include "../userspace/shell.h" #include "../userspace/shell.h"
#include "../libc/stdio.h" #include "../libc/stdio.h"
static void keyboard_callback(); static void keyboard_callback();
/* Keyboard scan codes map , layout is: standard US keyboard */ /* Keyboard scan codes map , layout is: standard US keyboard */
uint8_t keyboard_scan_codes[] = { uint8_t keyboard_scan_codes[] = {
0, (uint8_t)27, (uint8_t)'1', (uint8_t)'2', (uint8_t)'3', (uint8_t)'4', (uint8_t)'5', (uint8_t)'6', (uint8_t)'7', (uint8_t)'8', 0, (uint8_t)27, (uint8_t)'1', (uint8_t)'2', (uint8_t)'3', (uint8_t)'4', (uint8_t)'5', (uint8_t)'6', (uint8_t)'7', (uint8_t)'8',
(uint8_t)'0', (uint8_t)'0', (uint8_t)'-', (uint8_t)'=', (uint8_t)'\b', (uint8_t)'0', (uint8_t)'0', (uint8_t)'-', (uint8_t)'=', (uint8_t)'\b',
(uint8_t)'\t', (uint8_t)'\t',
(uint8_t)'q', (uint8_t)'w', (uint8_t)'e', (uint8_t)'r', (uint8_t)'q', (uint8_t)'w', (uint8_t)'e', (uint8_t)'r',
(uint8_t)'t', (uint8_t)'y', (uint8_t)'u', (uint8_t)'i', (uint8_t)'o', (uint8_t)'p', (uint8_t)'[', (uint8_t)']', (uint8_t)'\n', (uint8_t)'t', (uint8_t)'y', (uint8_t)'u', (uint8_t)'i', (uint8_t)'o', (uint8_t)'p', (uint8_t)'[', (uint8_t)']', (uint8_t)'\n',
0, 0,
(uint8_t)'a', (uint8_t)'s', (uint8_t)'d', (uint8_t)'f', (uint8_t)'g', (uint8_t)'h', (uint8_t)'j', (uint8_t)'k', (uint8_t)'l', (uint8_t)';', (uint8_t)'a', (uint8_t)'s', (uint8_t)'d', (uint8_t)'f', (uint8_t)'g', (uint8_t)'h', (uint8_t)'j', (uint8_t)'k', (uint8_t)'l', (uint8_t)';',
(uint8_t)'\'', (uint8_t)'`', 0, (uint8_t)'\'', (uint8_t)'`', 0,
(uint8_t)'\\', (uint8_t)'z', (uint8_t)'x', (uint8_t)'c', (uint8_t)'v', (uint8_t)'b', (uint8_t)'n', (uint8_t)'\\', (uint8_t)'z', (uint8_t)'x', (uint8_t)'c', (uint8_t)'v', (uint8_t)'b', (uint8_t)'n',
(uint8_t)'m', (uint8_t)',', (uint8_t)'.', (uint8_t)'/', 0, (uint8_t)'m', (uint8_t)',', (uint8_t)'.', (uint8_t)'/', 0,
(uint8_t)'*', (uint8_t)'*',
0, // Alt 0, // Alt
(uint8_t)' ', // Spacebar (uint8_t)' ', // Spacebar
0, // Caps lock 0, // Caps lock
0, // 59 - F1 key 0, // 59 - F1 key
0, // 59 - F1 key 0, // 59 - F1 key
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, // F10 0, // F10
0, // 69 - Num lock 0, // 69 - Num lock
0, // Scroll lock 0, // Scroll lock
0, // Home key 0, // Home key
0, // Up arrow 0, // Up arrow
0, // Page up 0, // Page up
(uint8_t)'-', (uint8_t)'-',
0, // Left arrow 0, // Left arrow
0, 0,
0, // Right arrow 0, // Right arrow
(uint8_t)'+', (uint8_t)'+',
0, // 79 End key 0, // 79 End key
0, // Down arrow 0, // Down arrow
0, // Page down 0, // Page down
0, // Insert key 0, // Insert key
0, // Delete key 0, // Delete key
0, 0, 0, 0, 0, 0,
0, // F11 key 0, // F11 key
0, // F12 key 0, // F12 key
0 // Others key are undefined 0 // Others key are undefined
}; };
uint8_t command[512]; // Max length of a single command uint8_t command[512]; // Max length of a single command
uint8_t temp[512]; uint8_t temp[512];
uint32_t cmd_index = 0; uint32_t cmd_index = 0;
uint32_t shiftdown = 0; uint32_t shiftdown = 0;
void clear() { void clear() {
for(uint16_t i = 0; i < 512; i++) for(uint16_t i = 0; i < 512; i++)
command[i] = 0; command[i] = 0;
} }
void clear_tmp(void) { void clear_tmp(void) {
for(uint16_t i = 0; i < 512; i++) for(uint16_t i = 0; i < 512; i++)
command[i] = 0; command[i] = 0;
} }
static void keyboard_callback() { static void keyboard_callback() {
uint8_t scan_code = inb(KB_DATA_PORT); // Read from keyboard uint8_t scan_code = inb(KB_DATA_PORT); // Read from keyboard
uint8_t keycode = keyboard_scan_codes[scan_code]; // Get ASCII value uint8_t keycode = keyboard_scan_codes[scan_code]; // Get ASCII value
if(scan_code & 0x80) { if(scan_code & 0x80) {
if(scan_code == 0xAA || scan_code == 0x86) if(scan_code == 0xAA || scan_code == 0x86)
shiftdown = 0; shiftdown = 0;
} else { } else {
// Handle backspace // Handle backspace
if(keycode == 0x08) { if(keycode == 0x08) {
if(cmd_index <= 0) // If at start of the prompt if(cmd_index <= 0) // If at start of the prompt
return; // Do not delete it. return; // Do not delete it.
cmd_index--; // Otherwise go back cmd_index--; // Otherwise go back
for(uint32_t i = 0; i < cmd_index; ++i) for(uint32_t i = 0; i < cmd_index; ++i)
temp[i] = command[i]; temp[i] = command[i];
clear(); clear();
for(uint32_t i = 0; i < cmd_index; ++i) for(uint32_t i = 0; i < cmd_index; ++i)
command[i] = temp[i]; command[i] = temp[i];
clear_tmp(); clear_tmp();
backspace(); backspace();
} else if(keycode == 0x0A) { // Handle Enter } else if(keycode == 0x0A) { // Handle Enter
processCommand(command); processCommand(command);
cmd_index = 0; cmd_index = 0;
clear(); clear();
init_prompt(); init_prompt();
} else { } else {
printf("%c", keycode); printf("%c", keycode);
command[cmd_index] = keycode; command[cmd_index] = keycode;
cmd_index++; cmd_index++;
} }
} }
} }
void init_keyboard() { void init_keyboard() {
register_interrupt_handler(IRQ1, &keyboard_callback); register_interrupt_handler(IRQ1, &keyboard_callback);
} }

View File

@ -1,17 +1,17 @@
/************************************** /*****************************************
* VulcanOS Kernel * * VulcanOS Kernel *
* Developed by Marco 'icebit' Cetica * * Developed by Marco 'icebit' Cetica *
* (c) 2019-2021 * * (c) 2019-2021 *
* Released under GPLv3 * * Released under GPLv3 *
* https://github.com/ice-bit/iceOS * * https://github.com/ice-bit/vulcanos *
***************************************/ *****************************************/
#ifndef _KEYBOARD_H_ #ifndef _KEYBOARD_H_
#define _KEYBOARD_H_ #define _KEYBOARD_H_
#include <stdint.h> #include <stdint.h>
#define KB_DATA_PORT 0x60 // Keyboard serial port #define KB_DATA_PORT 0x60 // Keyboard serial port
void init_keyboard(); void init_keyboard();
#endif #endif

View File

@ -1,27 +1,27 @@
/************************************** /*****************************************
* VulcanOS Kernel * * VulcanOS Kernel *
* Developed by Marco 'icebit' Cetica * * Developed by Marco 'icebit' Cetica *
* (c) 2019-2021 * * (c) 2019-2021 *
* Released under GPLv3 * * Released under GPLv3 *
* https://github.com/ice-bit/iceOS * * https://github.com/ice-bit/vulcanos *
***************************************/ *****************************************/
#ifndef _PORTS_H #ifndef _PORTS_H
#define _PORTS_H #define _PORTS_H
#include <stdint.h> #include <stdint.h>
/* outb: /* outb:
* Redirect data to port(high level interface for ports.asm) * Redirect data to port(high level interface for ports.asm)
* @param port: Output port to send data to. * @param port: Output port to send data to.
* @param data: The actual data to send to port * @param data: The actual data to send to port
*/ */
void outb(uint16_t port, uint16_t data); void outb(uint16_t port, uint16_t data);
/* inb: /* inb:
* Fetch data from a port, return a char * Fetch data from a port, return a char
* @param port: Input port to read data from. * @param port: Input port to read data from.
*/ */
uint8_t inb(uint16_t port); uint8_t inb(uint16_t port);
#endif #endif

View File

@ -1,39 +1,39 @@
#include "timer.h" #include "timer.h"
#include "isr.h" #include "isr.h"
#include "tty.h" #include "tty.h"
#include "../libc/string.h" #include "../libc/string.h"
#include "ports.h" #include "ports.h"
// Start tick at zero // Start tick at zero
uint32_t tick = 0; uint32_t tick = 0;
static void timer_callback(registers_t regs) { static void timer_callback(registers_t regs) {
tick++; tick++;
/* uint8_t buf[8]; /* uint8_t buf[8];
itoa(tick, buf, 10); itoa(tick, buf, 10);
kprint((uint8_t*)"Time: "); kprint((uint8_t*)"Time: ");
uitoa(tick, buf, 10); uitoa(tick, buf, 10);
kprint((uint8_t*)buf); kprint((uint8_t*)buf);
kprint((uint8_t*)"\n");*/ kprint((uint8_t*)"\n");*/
// Cast to void unused parameter // Cast to void unused parameter
UNUSED_PAR(regs); UNUSED_PAR(regs);
} }
void init_timer(uint32_t frequency) { void init_timer(uint32_t frequency) {
// Register a new ISR for IRQ0 // Register a new ISR for IRQ0
register_interrupt_handler(IRQ0, &timer_callback); register_interrupt_handler(IRQ0, &timer_callback);
/* As mentioned before, we'll send to PIT a value to divide for /* As mentioned before, we'll send to PIT a value to divide for
* his system clock(1.1931 MHz). We have to keep in mind that * his system clock(1.1931 MHz). We have to keep in mind that
* this value must fit into a 16 bits variable */ * this value must fit into a 16 bits variable */
uint32_t divisor = 1193180 / frequency; uint32_t divisor = 1193180 / frequency;
// Send command to the right port // Send command to the right port
outb(0x43, 0x36); outb(0x43, 0x36);
// The two divisor has to be sent byte-wise, to do this we split them in two parts // The two divisor has to be sent byte-wise, to do this we split them in two parts
uint8_t low = (uint8_t)(divisor & 0xFF); uint8_t low = (uint8_t)(divisor & 0xFF);
uint8_t high = (uint8_t)((divisor >> 8) & 0xFF); uint8_t high = (uint8_t)((divisor >> 8) & 0xFF);
// Send the frequency divisor // Send the frequency divisor
outb(0x40, low); outb(0x40, low);
outb(0x40, high); outb(0x40, high);
} }

View File

@ -1,41 +1,41 @@
/************************************** /*****************************************
* VulcanOS Kernel * * VulcanOS Kernel *
* Developed by Marco 'icebit' Cetica * * Developed by Marco 'icebit' Cetica *
* (c) 2019-2021 * * (c) 2019-2021 *
* Released under GPLv3 * * Released under GPLv3 *
* https://github.com/ice-bit/iceOS * * https://github.com/ice-bit/vulcanos *
***************************************/ *****************************************/
#ifndef _TIMER_H_ #ifndef _TIMER_H_
#define _TIMER_H_ #define _TIMER_H_
#include <stdint.h> #include <stdint.h>
/* /*
* The PIT(Programmable Interval Timer) is a chip that consist of an oscillator * The PIT(Programmable Interval Timer) is a chip that consist of an oscillator
* It's connected to IRQ0 and it can be configure at a user-defined rate * It's connected to IRQ0 and it can be configure at a user-defined rate
* between 10.Hz to 1.1931 MHz. The PIT is the primary method used to implement * between 10.Hz to 1.1931 MHz. The PIT is the primary method used to implement
* a system clock and for implement multitasking. * a system clock and for implement multitasking.
* The PIT's internal clock(~1.1931 MHz) is fed through a frequency divider that * The PIT's internal clock(~1.1931 MHz) is fed through a frequency divider that
* modulate the final signal. This chip has 3 channel, each with his own * modulate the final signal. This chip has 3 channel, each with his own
* frequency divider: * frequency divider:
* Channel 0: The most useful, it's output is connected to IRQ0 * Channel 0: The most useful, it's output is connected to IRQ0
* Channel 1: It were used to control refresh rates on DRAM(RAMs with capacitors) * Channel 1: It were used to control refresh rates on DRAM(RAMs with capacitors)
* Channel 2: Controls the PC speakers. * Channel 2: Controls the PC speakers.
* *
* In our case, we will use only channel 0. * In our case, we will use only channel 0.
* So we have to set up PIT at a frequency 'f', so it interrupts us at regular * So we have to set up PIT at a frequency 'f', so it interrupts us at regular
* intervals. We'll set the frequency to 100Hz(once every 10 ms); to do this * intervals. We'll set the frequency to 100Hz(once every 10 ms); to do this
* we'll send the PIT a divisor that will be divided for it's input frequency. * we'll send the PIT a divisor that will be divided for it's input frequency.
* E.g. -> divisor = 1193180 Hz(1.1931MHz) / 100 Hz * E.g. -> divisor = 1193180 Hz(1.1931MHz) / 100 Hz
* *
* Apart of that, the PIT has 4 registers: 0x40-0x42(data ports) and 0x43(command port) * Apart of that, the PIT has 4 registers: 0x40-0x42(data ports) and 0x43(command port)
*/ */
void init_timer(uint32_t frequency); void init_timer(uint32_t frequency);
extern uint32_t tick; extern uint32_t tick;
/* Since regs parameter(from timer_callback) will be unused /* Since regs parameter(from timer_callback) will be unused
* GCC(with -Werror flag) will throw an error, so we can avoid this * GCC(with -Werror flag) will throw an error, so we can avoid this
* using the following macro * using the following macro
*/ */
#define UNUSED_PAR(x) (void)(x) #define UNUSED_PAR(x) (void)(x)
#endif #endif

View File

@ -1,153 +1,153 @@
#include "tty.h" #include "tty.h"
#include "../libc/string.h" #include "../libc/string.h"
#include "ports.h" #include "ports.h"
#define VGA_PTR ((uint8_t*) VIDEO_MEM_ADDR) // Pointer to frame buffer #define VGA_PTR ((uint8_t*) VIDEO_MEM_ADDR) // Pointer to frame buffer
// Also define a 2 byte pointer because cells are 16 bits wide // Also define a 2 byte pointer because cells are 16 bits wide
#define UVGA_PTR ((uint16_t *)VIDEO_MEM_ADDR) #define UVGA_PTR ((uint16_t *)VIDEO_MEM_ADDR)
#define STRINGIZE(x) #x #define STRINGIZE(x) #x
#define STRINGIZE_VALUE_OF(x) STRINGIZE(x) #define STRINGIZE_VALUE_OF(x) STRINGIZE(x)
static uint32_t fb_col = 1; // X static uint32_t fb_col = 1; // X
static uint32_t fb_row = 0; // Y static uint32_t fb_row = 0; // Y
void write_cell(int16_t i, uint8_t c, uint8_t fg, uint8_t bg) { void write_cell(int16_t i, uint8_t c, uint8_t fg, uint8_t bg) {
uint8_t *fb = VGA_PTR; uint8_t *fb = VGA_PTR;
fb[i*2] = c; fb[i*2] = c;
fb[i*2 + 1] = ((bg & 0x0F) << 4) | (fg & 0x0F); fb[i*2 + 1] = ((bg & 0x0F) << 4) | (fg & 0x0F);
} }
void move_cursor(uint16_t pos) { void move_cursor(uint16_t pos) {
outb(VGA_CMD_PORT, VGA_HIGH_BYTE); outb(VGA_CMD_PORT, VGA_HIGH_BYTE);
outb(VGA_DATA_PORT, ((pos >> 8) & 0x00FF)); outb(VGA_DATA_PORT, ((pos >> 8) & 0x00FF));
outb(VGA_CMD_PORT, VGA_LOW_BYTE); outb(VGA_CMD_PORT, VGA_LOW_BYTE);
outb(VGA_DATA_PORT, pos & 0x00FF); outb(VGA_DATA_PORT, pos & 0x00FF);
} }
void cursor_adv() { // TODO: specify number of adv. with a parameter void cursor_adv() { // TODO: specify number of adv. with a parameter
if(fb_col < VGA_WIDTH - 1) if(fb_col < VGA_WIDTH - 1)
fb_col++; fb_col++;
else else
newline(); newline();
move_cursor(fb_col + (fb_row * VGA_WIDTH)); move_cursor(fb_col + (fb_row * VGA_WIDTH));
} }
void cursor_prev() { void cursor_prev() {
if(fb_col == 0) { if(fb_col == 0) {
if(fb_row == 0) if(fb_row == 0)
return; // If first row do not do anything return; // If first row do not do anything
fb_col = VGA_WIDTH - 1; fb_col = VGA_WIDTH - 1;
fb_row--; fb_row--;
} else } else
fb_col--; fb_col--;
move_cursor(fb_col + (fb_row * VGA_WIDTH)); move_cursor(fb_col + (fb_row * VGA_WIDTH));
} }
void backspace() { void backspace() {
uint16_t pos; uint16_t pos;
uint8_t c = ' '; uint8_t c = ' ';
fb_col--; fb_col--;
pos = fb_col + (fb_row * VGA_WIDTH); pos = fb_col + (fb_row * VGA_WIDTH);
write_cell(pos, c, WHITE, BLACK); write_cell(pos, c, WHITE, BLACK);
} }
void kprint_c(uint8_t *buf, uint32_t len, uint8_t fg, uint8_t bg) { void kprint_c(uint8_t *buf, uint32_t len, uint8_t fg, uint8_t bg) {
uint16_t pos; uint16_t pos;
for(uint32_t i = 0; i < len; i++) { for(uint32_t i = 0; i < len; i++) {
uint8_t c = buf[i]; uint8_t c = buf[i];
if(c == '\n' || c == '\r') if(c == '\n' || c == '\r')
newline(); newline();
else if(c == '\t') else if(c == '\t')
tab(); tab();
else { else {
pos = fb_col + (fb_row * VGA_WIDTH); pos = fb_col + (fb_row * VGA_WIDTH);
write_cell(pos, (uint8_t)c, fg, bg); write_cell(pos, (uint8_t)c, fg, bg);
cursor_adv(); cursor_adv();
} }
} }
} }
void kprint(uint8_t *buf) { void kprint(uint8_t *buf) {
kprint_c(buf, strlen(buf), WHITE, BLACK); kprint_c(buf, strlen(buf), WHITE, BLACK);
} }
void kprint_dec(uint32_t num) { void kprint_dec(uint32_t num) {
if(num == 0) { if(num == 0) {
uint8_t *buf = (uint8_t*)'0'; uint8_t *buf = (uint8_t*)'0';
kprint_c(buf, strlen(buf), WHITE, BLACK);; kprint_c(buf, strlen(buf), WHITE, BLACK);;
return; return;
} }
int32_t acc = num; int32_t acc = num;
uint8_t c[32]; uint8_t c[32];
int32_t i = 0; int32_t i = 0;
while(acc > 0) { while(acc > 0) {
c[i] = '0' + acc%10; c[i] = '0' + acc%10;
acc /= 10; acc /= 10;
i++; i++;
} }
c[i] = 0; c[i] = 0;
uint8_t c2[32]; uint8_t c2[32];
c2[i--] = 0; c2[i--] = 0;
uint32_t j = 0; uint32_t j = 0;
while(i >= 0) while(i >= 0)
c2[i--] = c[j++]; c2[i--] = c[j++];
kprint(c2); kprint(c2);
} }
void init_prompt() { void init_prompt() {
uint8_t user[64], hostname[64]; uint8_t user[64], hostname[64];
#ifdef DEFAULT_USER #ifdef DEFAULT_USER
strcpy(user, (uint8_t*)STRINGIZE_VALUE_OF(DEFAULT_USER)); strcpy(user, (uint8_t*)STRINGIZE_VALUE_OF(DEFAULT_USER));
#else #else
#error "-DDEFAULT_USER flag not set" #error "-DDEFAULT_USER flag not set"
#endif #endif
#ifdef DEFAULT_HOSTNAME #ifdef DEFAULT_HOSTNAME
strcpy(hostname, (uint8_t*)STRINGIZE_VALUE_OF(DEFAULT_HOSTNAME)); strcpy(hostname, (uint8_t*)STRINGIZE_VALUE_OF(DEFAULT_HOSTNAME));
#else #else
#error "-DDEFAULT_HOSTNAME flag not set" #error "-DDEFAULT_HOSTNAME flag not set"
#endif #endif
newline(); newline();
kprint_c(user, strlen(user), LIGHT_CYAN, BLACK); kprint_c(user, strlen(user), LIGHT_CYAN, BLACK);
kprint_c((uint8_t*)"@", 1, LIGHT_RED, BLACK); kprint_c((uint8_t*)"@", 1, LIGHT_RED, BLACK);
kprint_c(hostname, strlen(hostname), LIGHT_MAGENTA, BLACK); kprint_c(hostname, strlen(hostname), LIGHT_MAGENTA, BLACK);
kprint_c((uint8_t*)" #> ", 4, LIGHT_BLUE, BLACK); kprint_c((uint8_t*)" #> ", 4, LIGHT_BLUE, BLACK);
} }
void clear_prompt() { void clear_prompt() {
fb_col = 1; fb_col = 1;
fb_row = 0; fb_row = 0;
for(uint32_t i = 0; i < (VGA_WIDTH * VGA_HEIGHT); i++) for(uint32_t i = 0; i < (VGA_WIDTH * VGA_HEIGHT); i++)
write_cell(i, ' ', WHITE, BLACK); write_cell(i, ' ', WHITE, BLACK);
move_cursor(0); move_cursor(0);
} }
void clear_row(uint8_t row) { void clear_row(uint8_t row) {
for(size_t i = 0; i < VGA_WIDTH; i++) for(size_t i = 0; i < VGA_WIDTH; i++)
write_cell((row*VGA_WIDTH)+i, ' ', WHITE, BLACK); write_cell((row*VGA_WIDTH)+i, ' ', WHITE, BLACK);
} }
void scroll() { void scroll() {
uint16_t *fb = UVGA_PTR; uint16_t *fb = UVGA_PTR;
memmove(fb, fb+VGA_WIDTH, VGA_WIDTH*2*(VGA_HEIGHT*2-1)); memmove(fb, fb+VGA_WIDTH, VGA_WIDTH*2*(VGA_HEIGHT*2-1));
clear_row(VGA_HEIGHT - 1); clear_row(VGA_HEIGHT - 1);
} }
void newline() { void newline() {
if(fb_row < VGA_HEIGHT - 1) // If there's at least one cell add it if(fb_row < VGA_HEIGHT - 1) // If there's at least one cell add it
fb_row++; fb_row++;
else // Otherwise scroll framebuffer else // Otherwise scroll framebuffer
scroll(); scroll();
fb_col = 1; fb_col = 1;
move_cursor(fb_col + (fb_row * VGA_WIDTH)); move_cursor(fb_col + (fb_row * VGA_WIDTH));
} }
void tab() { void tab() {
for(uint8_t i = 0; i < 4; i++) for(uint8_t i = 0; i < 4; i++)
cursor_adv(); // Increment cursor 4 times cursor_adv(); // Increment cursor 4 times
} }

View File

@ -1,63 +1,63 @@
/************************************** /*****************************************
* VulcanOS Kernel * * VulcanOS Kernel *
* Developed by Marco 'icebit' Cetica * * Developed by Marco 'icebit' Cetica *
* (c) 2019-2021 * * (c) 2019-2021 *
* Released under GPLv3 * * Released under GPLv3 *
* https://github.com/ice-bit/iceOS * * https://github.com/ice-bit/vulcanos *
***************************************/ *****************************************/
#ifndef _TTY_H_ #ifndef _TTY_H_
#define _TTY_H_ #define _TTY_H_
#include <stdint.h> #include <stdint.h>
// TODO: write something about Frame Buffer // TODO: write something about Frame Buffer
// VGA colors // VGA colors
enum TTY_COLORS { enum TTY_COLORS {
BLACK, // 0 BLACK, // 0
BLUE, BLUE,
GREEN, GREEN,
CYAN, CYAN,
RED, RED,
MAGENTA, MAGENTA,
BROWN, BROWN,
LIGHT_GREY, LIGHT_GREY,
DARK_GREY, DARK_GREY,
LIGHT_BLUE, LIGHT_BLUE,
LIGHT_GREEN, LIGHT_GREEN,
LIGHT_CYAN, LIGHT_CYAN,
LIGHT_RED, LIGHT_RED,
LIGHT_MAGENTA, LIGHT_MAGENTA,
LIGHT_BROWN, LIGHT_BROWN,
WHITE // 15 WHITE // 15
}; };
/* Framebuffer properties */ /* Framebuffer properties */
#define VIDEO_MEM_ADDR 0x000B8000 // frame buffer address #define VIDEO_MEM_ADDR 0x000B8000 // frame buffer address
#define VGA_WIDTH 80 #define VGA_WIDTH 80
#define VGA_HEIGHT 25 #define VGA_HEIGHT 25
/* VGA I/O ports */ /* VGA I/O ports */
#define VGA_CMD_PORT 0x3D4 #define VGA_CMD_PORT 0x3D4
#define VGA_DATA_PORT 0x3D5 #define VGA_DATA_PORT 0x3D5
/* VGA I/O ports commands */ /* VGA I/O ports commands */
#define VGA_HIGH_BYTE 14 #define VGA_HIGH_BYTE 14
#define VGA_LOW_BYTE 15 #define VGA_LOW_BYTE 15
/* Kernel's VGA API */ /* Kernel's VGA API */
void write_cell(int16_t i, uint8_t c, uint8_t fg, uint8_t bg); void write_cell(int16_t i, uint8_t c, uint8_t fg, uint8_t bg);
void move_cursor(uint16_t pos); void move_cursor(uint16_t pos);
void cursor_adv(); void cursor_adv();
void backspace(); void backspace();
void kprint_c(uint8_t *buf, uint32_t len, uint8_t fg, uint8_t bg); void kprint_c(uint8_t *buf, uint32_t len, uint8_t fg, uint8_t bg);
void kprint(uint8_t *buf); void kprint(uint8_t *buf);
void kprint_dec(uint32_t num); void kprint_dec(uint32_t num);
void init_prompt(); void init_prompt();
void clear_prompt(); void clear_prompt();
void clear_row(uint8_t row); void clear_row(uint8_t row);
void scroll(); // Scroll one row void scroll(); // Scroll one row
void newline(); void newline();
void tab(); void tab();
#endif #endif

View File

@ -1,79 +1,79 @@
/************************************** /*****************************************
* VulcanOS Kernel * * VulcanOS Kernel *
* Developed by Marco 'icebit' Cetica * * Developed by Marco 'icebit' Cetica *
* (c) 2019-2021 * * (c) 2019-2021 *
* Released under GPLv3 * * Released under GPLv3 *
* https://github.com/ice-bit/iceOS * * https://github.com/ice-bit/vulcanos *
***************************************/ *****************************************/
#include "drivers/tty.h" #include "drivers/tty.h"
#include "drivers/gdt.h" #include "drivers/gdt.h"
#include "drivers/idt.h" #include "drivers/idt.h"
#include "drivers/timer.h" #include "drivers/timer.h"
#include "drivers/keyboard.h" #include "drivers/keyboard.h"
#include "mem/paging.h" #include "mem/paging.h"
#include "mem/kheap.h" #include "mem/kheap.h"
#include "mem/multiboot.h" #include "mem/multiboot.h"
#include "userspace/shell.h" #include "userspace/shell.h"
#include "libc/stdio.h" #include "libc/stdio.h"
#include "libc/panic.h" #include "libc/panic.h"
#include <stdint.h> #include <stdint.h>
#define PRTOK printf("\n["); printf_color(" OK ", LIGHT_GREEN, BLACK); printf("]"); // Ugly hack to print "[ OK ]" #define PRTOK printf("\n["); printf_color(" OK ", LIGHT_GREEN, BLACK); printf("]"); // Ugly hack to print "[ OK ]"
#define PRTAT printf("\n["); printf_color(" ** ", LIGHT_BROWN, BLACK); printf("]"); // Ugly hack to print "[ * ]" #define PRTAT printf("\n["); printf_color(" ** ", LIGHT_BROWN, BLACK); printf("]"); // Ugly hack to print "[ * ]"
#define PRTER printf("\n["); printf_color(" ERR ", LIGHT_RED, BLACK); printf("]"); // Ugly hack to print "[ ER ]" #define PRTER printf("\n["); printf_color(" ERR ", LIGHT_RED, BLACK); printf("]"); // Ugly hack to print "[ ER ]"
void kernel_main(unsigned long magic, uint32_t addr) { void kernel_main(unsigned long magic, uint32_t addr) {
// First of all, check if we're booted by a Multiboot-compliant boot loader // First of all, check if we're booted by a Multiboot-compliant boot loader
if(magic != MULTIBOOT2_BOOTLOADER_MAGIC) { if(magic != MULTIBOOT2_BOOTLOADER_MAGIC) {
PRTER PRTER
printf(" - Invalid magic number: %x\n", (unsigned)magic); printf(" - Invalid magic number: %x\n", (unsigned)magic);
PANIC("Invalid multiboot magic number"); PANIC("Invalid multiboot magic number");
} }
if(addr & 7) { if(addr & 7) {
PRTER PRTER
printf(" - Unaligned mbi: %x\n", addr); printf(" - Unaligned mbi: %x\n", addr);
PANIC("Unaligned multiboot MBI"); PANIC("Unaligned multiboot MBI");
} }
printf("Loading kernel, wait please..."); printf("Loading kernel, wait please...");
gdt_setup(); // Setup Global Descriptor Table gdt_setup(); // Setup Global Descriptor Table
PRTOK PRTOK
printf(" - Loaded GDT"); printf(" - Loaded GDT");
idt_setup(); // Setup Interrupt Descriptor Table idt_setup(); // Setup Interrupt Descriptor Table
PRTOK PRTOK
printf(" - Loaded IDT"); printf(" - Loaded IDT");
init_timer(1); // Initialize PIT driver init_timer(1); // Initialize PIT driver
PRTOK PRTOK
printf(" - Loaded PIT"); printf(" - Loaded PIT");
init_keyboard(); // Initialize keyboard driver init_keyboard(); // Initialize keyboard driver
PRTOK PRTOK
printf(" - Loaded PS/2 driver"); printf(" - Loaded PS/2 driver");
init_paging(); // Initialize paging init_paging(); // Initialize paging
PRTOK PRTOK
printf(" - Loaded Paging"); printf(" - Loaded Paging");
PRTAT PRTAT
printf(" - Testing heap...\t"); printf(" - Testing heap...\t");
uint32_t x = kmalloc(32), y = kmalloc(32); uint32_t x = kmalloc(32), y = kmalloc(32);
printf("x: %x, y: %x", x, y); printf("x: %x, y: %x", x, y);
kfree((void*)y); kfree((void*)y);
uint32_t z = kmalloc(8); uint32_t z = kmalloc(8);
printf(", z: %x", z); // If z is equal to y, heap's anti-fragmentation algorithm works printf(", z: %x", z); // If z is equal to y, heap's anti-fragmentation algorithm works
ASSERT(z == y); ASSERT(z == y);
kfree((void*)z), kfree((void*)x); kfree((void*)z), kfree((void*)x);
PRTOK PRTOK
printf(" - Heap works!"); printf(" - Heap works!");
init_prompt(); // Initialize frame buffer init_prompt(); // Initialize frame buffer
} }

View File

@ -1,11 +1,11 @@
OBJS = stdio.o string.o panic.o time.o OBJS = stdio.o string.o panic.o time.o
VER := $(shell git rev-parse --short HEAD) VER := $(shell git rev-parse --short HEAD)
CC = i686-elf-gcc # cross-compiler CC = i686-elf-gcc # cross-compiler
CFLAGS = -DVULCAN_VERSION=$(VER) -m32 -fno-stack-protector -ffreestanding -Wall -Wextra -Werror -g -c CFLAGS = -DVULCAN_VERSION=$(VER) -m32 -fno-stack-protector -ffreestanding -Wall -Wextra -Werror -g -c
all:${OBJS} all:${OBJS}
%.o: %.c %.o: %.c
$(CC) $(CFLAGS) $< -o $@ $(CC) $(CFLAGS) $< -o $@

View File

@ -1,51 +1,51 @@
#include "panic.h" #include "panic.h"
#include "../drivers/cpuid.h" #include "../drivers/cpuid.h"
#include "../libc/stdio.h" #include "../libc/stdio.h"
#include "../libc/string.h" #include "../libc/string.h"
#define KINFO printf("["); printf_color(" I ", LIGHT_RED, BLACK); printf("]: "); #define KINFO printf("["); printf_color(" I ", LIGHT_RED, BLACK); printf("]: ");
#define STRINGIZE(x) #x #define STRINGIZE(x) #x
#define STRINGIZE_VALUE_OF(x) STRINGIZE(x) #define STRINGIZE_VALUE_OF(x) STRINGIZE(x)
// We panic when we find a critical error, this function is called by assert macro // We panic when we find a critical error, this function is called by assert macro
extern void panic(const char *message, const char *file, uint32_t line) { extern void panic(const char *message, const char *file, uint32_t line) {
uint8_t version[64]; uint8_t version[64];
#ifdef VULCAN_VERSION #ifdef VULCAN_VERSION
strcpy(version, (uint8_t*)STRINGIZE_VALUE_OF(VULCAN_VERSION)); strcpy(version, (uint8_t*)STRINGIZE_VALUE_OF(VULCAN_VERSION));
#else #else
#error "-DVULCAN_VERSION flag not set" #error "-DVULCAN_VERSION flag not set"
#endif #endif
printf_color("=============================================\n", LIGHT_MAGENTA, BLACK); printf_color("=============================================\n", LIGHT_MAGENTA, BLACK);
printf_color(" .:: KERNEL PANIC ::. \n", LIGHT_RED, BLACK); printf_color(" .:: KERNEL PANIC ::. \n", LIGHT_RED, BLACK);
printf_color("Reason: ", LIGHT_BROWN, BLACK); printf_color("Reason: ", LIGHT_BROWN, BLACK);
printf("'%s' at '%s':%d\n", message, file, line); printf("'%s' at '%s':%d\n", message, file, line);
KINFO KINFO
printf_color("Disabling interrupts\n", LIGHT_GREEN, BLACK); printf_color("Disabling interrupts\n", LIGHT_GREEN, BLACK);
asm volatile("cli"); // Disable interrupts asm volatile("cli"); // Disable interrupts
KINFO KINFO
printf_color("Dropping you into an endless loop\n", LIGHT_GREEN, BLACK); printf_color("Dropping you into an endless loop\n", LIGHT_GREEN, BLACK);
KINFO KINFO
printf_color("Your are on your own now...good luck.\n", LIGHT_GREEN, BLACK); printf_color("Your are on your own now...good luck.\n", LIGHT_GREEN, BLACK);
KINFO KINFO
printf_color("VulcanOS version: ", LIGHT_GREEN, BLACK); printf_color("VulcanOS version: ", LIGHT_GREEN, BLACK);
printf_color((char*)version, LIGHT_CYAN, BLACK); printf_color((char*)version, LIGHT_CYAN, BLACK);
printf_color("\n\t\t (c) 2019-2021 Marco Cetica", LIGHT_BROWN, BLACK); printf_color("\n\t\t (c) 2019-2021 Marco Cetica", LIGHT_BROWN, BLACK);
printf_color("\n=============================================\n", LIGHT_MAGENTA, BLACK); printf_color("\n=============================================\n", LIGHT_MAGENTA, BLACK);
for(;;); for(;;);
} }
// Check for assertion failed, this function is called by assert macro // Check for assertion failed, this function is called by assert macro
extern void panic_assert(const char *file, uint32_t line, const char *desc) { extern void panic_assert(const char *file, uint32_t line, const char *desc) {
asm volatile("cli"); // Disable interrupts asm volatile("cli"); // Disable interrupts
kprint((uint8_t*)"ASSERTION-FAILED("); kprint((uint8_t*)"ASSERTION-FAILED(");
kprint((uint8_t*)desc); kprint((uint8_t*)desc);
kprint((uint8_t*)") at "); kprint((uint8_t*)") at ");
kprint((uint8_t*)file); kprint((uint8_t*)file);
kprint((uint8_t*)":"); kprint((uint8_t*)":");
kprint_dec(line); kprint_dec(line);
kprint((uint8_t*)"\n"); kprint((uint8_t*)"\n");
// Now hang on forever // Now hang on forever
for(;;); for(;;);
} }

View File

@ -1,20 +1,20 @@
/************************************** /*****************************************
* VulcanOS Kernel * * VulcanOS Kernel *
* Developed by Marco 'icebit' Cetica * * Developed by Marco 'icebit' Cetica *
* (c) 2019-2021 * * (c) 2019-2021 *
* Released under GPLv3 * * Released under GPLv3 *
* https://github.com/ice-bit/iceOS * * https://github.com/ice-bit/vulcanos *
***************************************/ *****************************************/
#ifndef PANIC_H #ifndef PANIC_H
#define PANIC_H #define PANIC_H
#include <stdint.h> #include <stdint.h>
#include "../drivers/tty.h" #include "../drivers/tty.h"
#define PANIC(msg) panic(msg, __FILE__, __LINE__); #define PANIC(msg) panic(msg, __FILE__, __LINE__);
#define ASSERT(b) ((b) ? (void)0 : panic_assert(__FILE__, __LINE__, #b)) #define ASSERT(b) ((b) ? (void)0 : panic_assert(__FILE__, __LINE__, #b))
extern void panic(const char *message, const char *file, uint32_t line); extern void panic(const char *message, const char *file, uint32_t line);
extern void panic_assert(const char *file, uint32_t line, const char *desc); extern void panic_assert(const char *file, uint32_t line, const char *desc);
#endif #endif

View File

@ -1,59 +1,59 @@
#include "stdio.h" #include "stdio.h"
#include "string.h" #include "string.h"
#include "../drivers/tty.h" #include "../drivers/tty.h"
int printf(const char *format, ...) { int printf(const char *format, ...) {
uint8_t buf[20],c,*s; uint8_t buf[20],c,*s;
int val; int val;
int32_t uval; int32_t uval;
va_list ap; va_list ap;
va_start(ap, format); va_start(ap, format);
for(size_t i = 0; i < strlen((uint8_t*)format); i++) { for(size_t i = 0; i < strlen((uint8_t*)format); i++) {
if(format[i] == '%') { if(format[i] == '%') {
i++; i++;
while(format[i] == ' ') while(format[i] == ' ')
i++; i++;
switch(format[i]) { switch(format[i]) {
case 'i': case 'i':
val = va_arg(ap, int); val = va_arg(ap, int);
itoa(val, buf, 10); itoa(val, buf, 10);
kprint(buf); kprint(buf);
break; break;
case 'x': case 'x':
uval = va_arg(ap, uint32_t); uval = va_arg(ap, uint32_t);
uitoa(uval, buf, 16); uitoa(uval, buf, 16);
kprint(buf); kprint(buf);
break; break;
case 'd': case 'd':
uval = va_arg(ap, uint32_t); uval = va_arg(ap, uint32_t);
uitoa(uval, buf, 10); uitoa(uval, buf, 10);
kprint(buf); kprint(buf);
break; break;
case 'c': case 'c':
c = (uint8_t)va_arg(ap, uint32_t); c = (uint8_t)va_arg(ap, uint32_t);
kprint_c(&c, 1, WHITE, BLACK); kprint_c(&c, 1, WHITE, BLACK);
break; break;
case 's': case 's':
s = va_arg(ap, uint8_t*); s = va_arg(ap, uint8_t*);
kprint(s); kprint(s);
break; break;
default: default:
kprint_c((uint8_t*)format+i, 1, WHITE, BLACK); kprint_c((uint8_t*)format+i, 1, WHITE, BLACK);
} }
} else } else
kprint_c((uint8_t*)format+i, 1, WHITE, BLACK); kprint_c((uint8_t*)format+i, 1, WHITE, BLACK);
} }
va_end(ap); va_end(ap);
return 0; return 0;
} }
int printf_color(const char *format, uint8_t fg, uint8_t bg) { int printf_color(const char *format, uint8_t fg, uint8_t bg) {
kprint_c((uint8_t*)format, strlen((uint8_t*)format), fg, bg); kprint_c((uint8_t*)format, strlen((uint8_t*)format), fg, bg);
return 0; return 0;
} }
void puts(const char *buf) { void puts(const char *buf) {
printf("%s\n", buf); printf("%s\n", buf);
} }

View File

@ -1,19 +1,19 @@
/************************************** /*****************************************
* VulcanOS Kernel * * VulcanOS Kernel *
* Developed by Marco 'icebit' Cetica * * Developed by Marco 'icebit' Cetica *
* (c) 2019-2021 * * (c) 2019-2021 *
* Released under GPLv3 * * Released under GPLv3 *
* https://github.com/ice-bit/iceOS * * https://github.com/ice-bit/vulcanos *
***************************************/ *****************************************/
#ifndef _STDIO_H_ #ifndef _STDIO_H_
#define _STDIO_H_ #define _STDIO_H_
#include <stdint.h> #include <stdint.h>
#include <stddef.h> #include <stddef.h>
#include <stdarg.h> #include <stdarg.h>
int printf(const char *format, ...); int printf(const char *format, ...);
int printf_color(const char *format, uint8_t fg, uint8_t bg); // Only for string for now int printf_color(const char *format, uint8_t fg, uint8_t bg); // Only for string for now
void puts(const char *buf); void puts(const char *buf);
#endif #endif

View File

@ -1,150 +1,150 @@
#include "string.h" #include "string.h"
// C library implementation // C library implementation
int32_t strcmp(const uint8_t *s1, const uint8_t *s2) { int32_t strcmp(const uint8_t *s1, const uint8_t *s2) {
while ((*s1) && (*s1 == *s2)) { while ((*s1) && (*s1 == *s2)) {
s1++; s1++;
s2++; s2++;
} }
return (*(uint8_t*)s1 - *(uint8_t*)s2); return (*(uint8_t*)s1 - *(uint8_t*)s2);
} }
uint8_t *itoa(int32_t val, uint8_t *buf, uint32_t radix) { uint8_t *itoa(int32_t val, uint8_t *buf, uint32_t radix) {
uint32_t i = 0; uint32_t i = 0;
uint32_t start = i; uint32_t start = i;
if(val < 0 && radix == 10) { if(val < 0 && radix == 10) {
buf[i++] = '-'; buf[i++] = '-';
start = i; start = i;
} }
if(radix == 10) { if(radix == 10) {
buf[i++] = '0'; buf[i++] = '0';
buf[i++] = 'x'; buf[i++] = 'x';
start = i; start = i;
} }
int x = val; int x = val;
do { do {
int a = x % radix; int a = x % radix;
if(a < 10) if(a < 10)
buf[i++] = a + '0'; buf[i++] = a + '0';
else else
buf[i++]= a + 'a' - 10; buf[i++]= a + 'a' - 10;
} while(x /= radix); } while(x /= radix);
uint8_t *s = buf+start; uint8_t *s = buf+start;
uint8_t *e = buf+(i-1); uint8_t *e = buf+(i-1);
while(s < e) { while(s < e) {
uint8_t t = *s; uint8_t t = *s;
*s = *e; *s = *e;
*e = t; *e = t;
i++; i++;
e--; e--;
} }
buf[i] = 0; buf[i] = 0;
return buf; return buf;
} }
uint8_t *uitoa(uint32_t val, uint8_t *buf, uint32_t radix) { uint8_t *uitoa(uint32_t val, uint8_t *buf, uint32_t radix) {
uint32_t i = 0; uint32_t i = 0;
uint32_t start = i; uint32_t start = i;
uint32_t x = val; uint32_t x = val;
if(radix == 16) { if(radix == 16) {
buf[i++] = '0'; buf[i++] = '0';
buf[i++] = 'x'; buf[i++] = 'x';
start = i; start = i;
} }
do { do {
uint32_t a = x % radix; uint32_t a = x % radix;
if(a < 10) if(a < 10)
buf[i++] = a + '0'; buf[i++] = a + '0';
else else
buf[i++] = a + 'a' - 10; buf[i++] = a + 'a' - 10;
} while(x /= radix); } while(x /= radix);
uint8_t *s = buf+start; uint8_t *s = buf+start;
uint8_t *e = buf+(i-1); uint8_t *e = buf+(i-1);
while(s < e) { while(s < e) {
uint8_t t = *s; uint8_t t = *s;
*s = *e; *s = *e;
*e = t; *e = t;
s++; s++;
e--; e--;
} }
buf[i] = 0; buf[i] = 0;
return buf; return buf;
} }
size_t strlen(const uint8_t *buf) { size_t strlen(const uint8_t *buf) {
uint32_t i = 0; uint32_t i = 0;
while(buf[i] != 0) while(buf[i] != 0)
i++; i++;
return i; return i;
} }
uint8_t *strcpy(uint8_t *dst, const uint8_t *src) { uint8_t *strcpy(uint8_t *dst, const uint8_t *src) {
uint8_t *dst_p = dst; uint8_t *dst_p = dst;
while((*dst++ = *src++)); while((*dst++ = *src++));
return dst_p; return dst_p;
} }
void strcat(void *dest, const void *src) { void strcat(void *dest, const void *src) {
uint8_t *end = (uint8_t*)dest + strlen(dest); uint8_t *end = (uint8_t*)dest + strlen(dest);
memcpy((uint8_t*)end, (uint8_t*)src, strlen((uint8_t*)src)); memcpy((uint8_t*)end, (uint8_t*)src, strlen((uint8_t*)src));
end += strlen((uint8_t*)src); end += strlen((uint8_t*)src);
*end = '\0'; *end = '\0';
} }
/* Worst memset implementation /* Worst memset implementation
* i could find on the net. * i could find on the net.
* however it works so... */ * however it works so... */
void *memset(void *s, uint32_t c, size_t n) { void *memset(void *s, uint32_t c, size_t n) {
char *mem = (char*)s; char *mem = (char*)s;
for(size_t i = 0; i < n; i++) for(size_t i = 0; i < n; i++)
mem[i] = (uint8_t)c; mem[i] = (uint8_t)c;
return s; return s;
} }
void *memcpy(void *dst, void const *src, uint32_t n) { void *memcpy(void *dst, void const *src, uint32_t n) {
uint8_t *ret = dst; uint8_t *ret = dst;
uint8_t *p = dst; uint8_t *p = dst;
const uint8_t *q = src; const uint8_t *q = src;
while(n--) while(n--)
*p++ = *q++; *p++ = *q++;
return ret; return ret;
} }
void *memmove(void *dst, const void *src, size_t len) { void *memmove(void *dst, const void *src, size_t len) {
char *dstmem = (char*)dst; char *dstmem = (char*)dst;
char *srcmem = (char*)src; char *srcmem = (char*)src;
for(size_t i = 0; i < len; i++) for(size_t i = 0; i < len; i++)
dstmem[i] = srcmem[i]; dstmem[i] = srcmem[i];
return dstmem; return dstmem;
} }
void strupper(uint8_t *str) { void strupper(uint8_t *str) {
for(unsigned int i = 0; i < strlen(str); i++) { for(unsigned int i = 0; i < strlen(str); i++) {
if(str[i] == 'a' && str[i] < 'z') if(str[i] == 'a' && str[i] < 'z')
str[i] &= 0x4F; str[i] &= 0x4F;
} }
} }
void strlower(uint8_t *str) { void strlower(uint8_t *str) {
for(unsigned int i = 0; i < strlen(str); i++) { for(unsigned int i = 0; i < strlen(str); i++) {
if(str[i] == 'A' && str[i] < 'Z') if(str[i] == 'A' && str[i] < 'Z')
str[i] |= 0x60; str[i] |= 0x60;
} }
} }

View File

@ -1,26 +1,26 @@
/************************************** /*****************************************
* VulcanOS Kernel * * VulcanOS Kernel *
* Developed by Marco 'icebit' Cetica * * Developed by Marco 'icebit' Cetica *
* (c) 2019-2021 * * (c) 2019-2021 *
* Released under GPLv3 * * Released under GPLv3 *
* https://github.com/ice-bit/iceOS * * https://github.com/ice-bit/vulcanos *
***************************************/ *****************************************/
#ifndef _STRING_H_ #ifndef _STRING_H_
#define _STRING_H_ #define _STRING_H_
#include <stdint.h> // For uinx_t #include <stdint.h> // For uinx_t
#include <stddef.h> // For size_t #include <stddef.h> // For size_t
int32_t strcmp(const uint8_t *s1, const uint8_t *s2); int32_t strcmp(const uint8_t *s1, const uint8_t *s2);
uint8_t *itoa(int32_t val, uint8_t *buf, uint32_t radix); uint8_t *itoa(int32_t val, uint8_t *buf, uint32_t radix);
uint8_t *uitoa(uint32_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); size_t strlen(const uint8_t *buf);
uint8_t *strcpy(uint8_t *dst, const uint8_t *src); uint8_t *strcpy(uint8_t *dst, const uint8_t *src);
void strcat(void *dest, const void *src); void strcat(void *dest, const void *src);
void *memset(void *s, uint32_t c, size_t n); void *memset(void *s, uint32_t c, size_t n);
void *memmove(void *dst, const void *src, size_t len); void *memmove(void *dst, const void *src, size_t len);
void *memcpy(void *dst, void const *src, uint32_t n); void *memcpy(void *dst, void const *src, uint32_t n);
void strupper(uint8_t *str); void strupper(uint8_t *str);
void strlower(uint8_t *str); void strlower(uint8_t *str);
#endif #endif

View File

@ -1,38 +1,38 @@
#include "time.h" #include "time.h"
#include "../drivers/ports.h" #include "../drivers/ports.h"
// Check whether CMOS is updated or not // Check whether CMOS is updated or not
static uint8_t is_cmos_updated() { static uint8_t is_cmos_updated() {
outb(CMOS_ADDRESS, 0x0A); outb(CMOS_ADDRESS, 0x0A);
return (inb(CMOS_DATA) & 0x80); return (inb(CMOS_DATA) & 0x80);
} }
// Get CMOS register's status // Get CMOS register's status
static uint8_t reg_status(int32_t reg) { static uint8_t reg_status(int32_t reg) {
outb(CMOS_ADDRESS, reg); outb(CMOS_ADDRESS, reg);
return inb(CMOS_DATA); return inb(CMOS_DATA);
} }
time_t cmos_reader() { time_t cmos_reader() {
while(is_cmos_updated()); // Wait until the CMOS is being updated while(is_cmos_updated()); // Wait until the CMOS is being updated
time_t tm; time_t tm;
tm.second = BCD_CONVERTER(reg_status(TIME_R_SECOND)); tm.second = BCD_CONVERTER(reg_status(TIME_R_SECOND));
tm.minute = BCD_CONVERTER(reg_status(TIME_R_MINUTE)); tm.minute = BCD_CONVERTER(reg_status(TIME_R_MINUTE));
tm.hour = BCD_CONVERTER(reg_status(TIME_R_HOUR)); tm.hour = BCD_CONVERTER(reg_status(TIME_R_HOUR));
tm.day = BCD_CONVERTER(reg_status(TIME_R_DAY)); tm.day = BCD_CONVERTER(reg_status(TIME_R_DAY));
tm.month = BCD_CONVERTER(reg_status(TIME_R_MONTH)); tm.month = BCD_CONVERTER(reg_status(TIME_R_MONTH));
tm.year = BCD_CONVERTER(reg_status(TIME_R_YEAR)); tm.year = BCD_CONVERTER(reg_status(TIME_R_YEAR));
return tm; return tm;
} }
uint32_t get_time(uint32_t field) { uint32_t get_time(uint32_t field) {
while(is_cmos_updated()); // Wait the CMOS is being updated while(is_cmos_updated()); // Wait the CMOS is being updated
return BCD_CONVERTER(reg_status(field)); return BCD_CONVERTER(reg_status(field));
} }

View File

@ -1,42 +1,42 @@
/************************************** /*****************************************
* VulcanOS Kernel * * VulcanOS Kernel *
* Developed by Marco 'icebit' Cetica * * Developed by Marco 'icebit' Cetica *
* (c) 2019-2021 * * (c) 2019-2021 *
* Released under GPLv3 * * Released under GPLv3 *
* https://github.com/ice-bit/iceOS * * https://github.com/ice-bit/vulcanos *
***************************************/ *****************************************/
/* Get time reading the RTC(real time clock) CMOS on the motherboard */ /* Get time reading the RTC(real time clock) CMOS on the motherboard */
#ifndef TIME_H #ifndef TIME_H
#define TIME_H #define TIME_H
#include <stdint.h> #include <stdint.h>
// Define RTC field registers // Define RTC field registers
#define TIME_R_YEAR 0x09 #define TIME_R_YEAR 0x09
#define TIME_R_MONTH 0x08 #define TIME_R_MONTH 0x08
#define TIME_R_DAY 0x07 #define TIME_R_DAY 0x07
#define TIME_R_HOUR 0x06 #define TIME_R_HOUR 0x06
#define TIME_R_MINUTE 0x05 #define TIME_R_MINUTE 0x05
#define TIME_R_SECOND 0x04 #define TIME_R_SECOND 0x04
//#define TIME_R_CENTURY 0x32 //#define TIME_R_CENTURY 0x32
// Define RTC address // Define RTC address
#define CMOS_ADDRESS 0x70 #define CMOS_ADDRESS 0x70
#define CMOS_DATA 0x71 #define CMOS_DATA 0x71
// Convert BCD encoed values to binary // Convert BCD encoed values to binary
#define BCD_CONVERTER(n) ((n / 16) * 10 + (n & 0xF)) #define BCD_CONVERTER(n) ((n / 16) * 10 + (n & 0xF))
typedef struct { typedef struct {
uint8_t second; uint8_t second;
uint8_t minute; uint8_t minute;
uint8_t hour; uint8_t hour;
uint8_t day; uint8_t day;
uint8_t month; uint8_t month;
uint8_t year; uint8_t year;
} time_t; } time_t;
time_t cmos_reader(); time_t cmos_reader();
uint32_t get_time(uint32_t field); uint32_t get_time(uint32_t field);
#endif #endif

View File

@ -1,9 +1,9 @@
OBJS = paging.o kheap.o ordered_array.o OBJS = paging.o kheap.o ordered_array.o
CC = i686-elf-gcc # cross-compiler CC = i686-elf-gcc # cross-compiler
CFLAGS = -m32 -fno-stack-protector -ffreestanding -Wall -Wextra -Werror -g -c CFLAGS = -m32 -fno-stack-protector -ffreestanding -Wall -Wextra -Werror -g -c
all:${OBJS} all:${OBJS}
%.o: %.c %.o: %.c
${CC} ${CFLAGS} $< -o $@ ${CC} ${CFLAGS} $< -o $@

View File

@ -1,329 +1,329 @@
#include "kheap.h" #include "kheap.h"
#include "paging.h" #include "paging.h"
#include "../libc/panic.h" #include "../libc/panic.h"
extern uint32_t end; extern uint32_t end;
uint32_t placement_addr = (uint32_t)&end; uint32_t placement_addr = (uint32_t)&end;
extern page_directory_t *kernel_directory; extern page_directory_t *kernel_directory;
heap_t *kheap = 0; heap_t *kheap = 0;
uint32_t kmalloc_int(uint32_t sz, int32_t align, uint32_t *phys) { uint32_t kmalloc_int(uint32_t sz, int32_t align, uint32_t *phys) {
if(kheap != 0) { if(kheap != 0) {
void *addr = alloc(sz, (uint8_t)align, kheap); void *addr = alloc(sz, (uint8_t)align, kheap);
if(phys != 0) { if(phys != 0) {
page_t *page = get_page((uint32_t)addr, 0, kernel_directory); page_t *page = get_page((uint32_t)addr, 0, kernel_directory);
*phys = page->fr*0x1000 + ((uint32_t)addr&0xFFF); *phys = page->fr*0x1000 + ((uint32_t)addr&0xFFF);
} }
return (uint32_t)addr; return (uint32_t)addr;
} else { } else {
if(align == 1 && (placement_addr & 0xFFFFF000)) { if(align == 1 && (placement_addr & 0xFFFFF000)) {
placement_addr &= 0xFFFFF000; placement_addr &= 0xFFFFF000;
placement_addr += 0x1000; placement_addr += 0x1000;
} }
if(phys) if(phys)
*phys = placement_addr; *phys = placement_addr;
uint32_t tmp = placement_addr; uint32_t tmp = placement_addr;
placement_addr += sz; placement_addr += sz;
return tmp; return tmp;
} }
} }
void kfree(void *p) { void kfree(void *p) {
free(p, kheap); free(p, kheap);
} }
uint32_t kmalloc_a(uint32_t sz) { uint32_t kmalloc_a(uint32_t sz) {
return kmalloc_int(sz, 1, 0); return kmalloc_int(sz, 1, 0);
} }
uint32_t kmalloc_p(uint32_t sz, uint32_t *phys) { uint32_t kmalloc_p(uint32_t sz, uint32_t *phys) {
return kmalloc_int(sz, 0, phys); return kmalloc_int(sz, 0, phys);
} }
uint32_t kmalloc_ap(uint32_t sz, uint32_t *phys) { uint32_t kmalloc_ap(uint32_t sz, uint32_t *phys) {
return kmalloc_int(sz, 1, phys); return kmalloc_int(sz, 1, phys);
} }
uint32_t kmalloc(uint32_t sz) { uint32_t kmalloc(uint32_t sz) {
return kmalloc_int(sz, 0, 0); return kmalloc_int(sz, 0, 0);
} }
static void expand(uint32_t new_size, heap_t *heap) { static void expand(uint32_t new_size, heap_t *heap) {
// First check if new size is greater than older one // First check if new size is greater than older one
ASSERT(new_size > heap->end_address - heap->start_address); ASSERT(new_size > heap->end_address - heap->start_address);
// Get nearest page boundary // Get nearest page boundary
if((new_size&0xFFFFF000) != 0) { if((new_size&0xFFFFF000) != 0) {
new_size &= 0xFFFFF000; new_size &= 0xFFFFF000;
new_size += 0x1000; new_size += 0x1000;
} }
// Check if new size is not greater than maximum size // Check if new size is not greater than maximum size
ASSERT(heap->start_address+new_size <= heap->max_address); ASSERT(heap->start_address+new_size <= heap->max_address);
uint32_t old_size = heap->end_address - heap->start_address; uint32_t old_size = heap->end_address - heap->start_address;
uint32_t it = old_size; uint32_t it = old_size;
while(it < new_size) { while(it < new_size) {
alloc_frame(get_page(heap->start_address+it, 1, kernel_directory), alloc_frame(get_page(heap->start_address+it, 1, kernel_directory),
(heap->supervisor) ? 1 : 0, (heap->readonly) ? 0 : 1); (heap->supervisor) ? 1 : 0, (heap->readonly) ? 0 : 1);
it += 0x1000; // Page size it += 0x1000; // Page size
} }
heap->end_address = heap->start_address+new_size; heap->end_address = heap->start_address+new_size;
} }
static uint32_t contract(uint32_t new_size, heap_t *heap) { static uint32_t contract(uint32_t new_size, heap_t *heap) {
ASSERT(new_size < heap->end_address-heap->start_address); ASSERT(new_size < heap->end_address-heap->start_address);
if(new_size&0x1000) { if(new_size&0x1000) {
new_size &= 0x1000; new_size &= 0x1000;
new_size += 0x1000; new_size += 0x1000;
} }
if(new_size < HEAP_MIN_SIZE) if(new_size < HEAP_MIN_SIZE)
new_size = HEAP_MIN_SIZE; new_size = HEAP_MIN_SIZE;
uint32_t old_size = heap->end_address - heap->start_address; uint32_t old_size = heap->end_address - heap->start_address;
uint32_t it = old_size - 0x1000; uint32_t it = old_size - 0x1000;
while(new_size < it) { while(new_size < it) {
free_frame(get_page(heap->start_address+it, 0, kernel_directory)); free_frame(get_page(heap->start_address+it, 0, kernel_directory));
it -= 0x1000; it -= 0x1000;
} }
heap->end_address = heap->start_address + new_size; heap->end_address = heap->start_address + new_size;
return new_size; return new_size;
} }
static uint32_t find_smallest_hole(uint32_t size, uint8_t page_align, heap_t *heap) { static uint32_t find_smallest_hole(uint32_t size, uint8_t page_align, heap_t *heap) {
uint32_t it = 0; uint32_t it = 0;
// Find smallest hole that fit our request // Find smallest hole that fit our request
while(it < heap->index.size) { while(it < heap->index.size) {
header_t *head = (header_t*)lookup_ordered_array(it, &heap->index); header_t *head = (header_t*)lookup_ordered_array(it, &heap->index);
if(page_align > 0) { if(page_align > 0) {
// page must be aligned? // page must be aligned?
uint32_t location = (uint32_t)head; uint32_t location = (uint32_t)head;
uint32_t offset = 0; uint32_t offset = 0;
if(((location+sizeof(header_t)) & 0xFFFFF000) != 0) if(((location+sizeof(header_t)) & 0xFFFFF000) != 0)
offset = 0x1000 - (location+sizeof(header_t))%0x1000; offset = 0x1000 - (location+sizeof(header_t))%0x1000;
uint32_t hole_size = (uint32_t)head->size - offset; uint32_t hole_size = (uint32_t)head->size - offset;
// Check if we can fit this page in that hole // Check if we can fit this page in that hole
if(hole_size >= (uint32_t)size) if(hole_size >= (uint32_t)size)
break; break;
} else if(head->size >= size) } else if(head->size >= size)
break; break;
it++; it++;
} }
// If we didn't find anything // If we didn't find anything
if(it == heap->index.size) if(it == heap->index.size)
return -1; return -1;
else else
return it; return it;
} }
static uint8_t header_t_less_than(void *a, void *b) { static uint8_t header_t_less_than(void *a, void *b) {
return (((header_t*)a)->size < ((header_t*)b)->size)?1:0; return (((header_t*)a)->size < ((header_t*)b)->size)?1:0;
} }
heap_t *create_heap(uint32_t start, uint32_t end_addr, uint32_t max, uint8_t supervisor, uint8_t readonly) { heap_t *create_heap(uint32_t start, uint32_t end_addr, uint32_t max, uint8_t supervisor, uint8_t readonly) {
heap_t *heap = (heap_t*)kmalloc(sizeof(heap_t)); heap_t *heap = (heap_t*)kmalloc(sizeof(heap_t));
ASSERT(start%0x1000 == 0); ASSERT(start%0x1000 == 0);
ASSERT(end_addr%0x1000 == 0); ASSERT(end_addr%0x1000 == 0);
// Initialize the index // Initialize the index
heap->index = place_ordered_array((void*)start, HEAP_INDEX_SIZE, &header_t_less_than); heap->index = place_ordered_array((void*)start, HEAP_INDEX_SIZE, &header_t_less_than);
// Shift start address to the right // Shift start address to the right
start += sizeof(type_t) * HEAP_INDEX_SIZE; start += sizeof(type_t) * HEAP_INDEX_SIZE;
// Check if start address is page-aligned // Check if start address is page-aligned
if ((start & 0xFFFFF000) != 0) { if ((start & 0xFFFFF000) != 0) {
start &= 0xFFFFF000; start &= 0xFFFFF000;
start += 0x1000; start += 0x1000;
} }
// Store vars into heap // Store vars into heap
heap->start_address = start; heap->start_address = start;
heap->end_address = end_addr; heap->end_address = end_addr;
heap->max_address = max; heap->max_address = max;
heap->supervisor = supervisor; heap->supervisor = supervisor;
heap->readonly = readonly; heap->readonly = readonly;
header_t *hole = (header_t*)start; header_t *hole = (header_t*)start;
hole->size = end_addr - start; hole->size = end_addr - start;
hole->magic = HEAP_MAGIC; hole->magic = HEAP_MAGIC;
hole->is_hole = 1; hole->is_hole = 1;
insert_ordered_array((void*)hole, &heap->index); insert_ordered_array((void*)hole, &heap->index);
return heap; return heap;
} }
void *alloc(uint32_t size, uint8_t page_align, heap_t *heap) { void *alloc(uint32_t size, uint8_t page_align, heap_t *heap) {
uint32_t new_size = size + sizeof(header_t) + sizeof(footer_t); uint32_t new_size = size + sizeof(header_t) + sizeof(footer_t);
// Find smallest hole suitable // Find smallest hole suitable
uint32_t it = find_smallest_hole(new_size, page_align, heap); uint32_t it = find_smallest_hole(new_size, page_align, heap);
if((int32_t)it == -1) { if((int32_t)it == -1) {
uint32_t old_len = heap->end_address - heap->start_address; uint32_t old_len = heap->end_address - heap->start_address;
uint32_t old_end_addr = heap->end_address; uint32_t old_end_addr = heap->end_address;
// Allocate more space // Allocate more space
expand(old_len+new_size, heap); expand(old_len+new_size, heap);
uint32_t new_len = heap->end_address - heap->start_address; uint32_t new_len = heap->end_address - heap->start_address;
it = 0; it = 0;
uint32_t idx = -1; uint32_t value = 0x0; uint32_t idx = -1; uint32_t value = 0x0;
while(it < heap->index.size) { while(it < heap->index.size) {
uint32_t tmp = (uint32_t)lookup_ordered_array(it, &heap->index); uint32_t tmp = (uint32_t)lookup_ordered_array(it, &heap->index);
if(tmp > value) { if(tmp > value) {
value = tmp; value = tmp;
idx = it; idx = it;
} }
it++; it++;
} }
// If no headers has been found, add a new one // If no headers has been found, add a new one
if((int32_t)idx == -1) { if((int32_t)idx == -1) {
header_t *head = (header_t*)old_end_addr; header_t *head = (header_t*)old_end_addr;
head->magic = HEAP_MAGIC; head->magic = HEAP_MAGIC;
head->size = new_len - old_len; head->size = new_len - old_len;
head->is_hole = 1; head->is_hole = 1;
footer_t *foot = (footer_t*)(old_end_addr + head->size - sizeof(footer_t)); footer_t *foot = (footer_t*)(old_end_addr + head->size - sizeof(footer_t));
foot->magic = HEAP_MAGIC; foot->magic = HEAP_MAGIC;
foot->header = head; foot->header = head;
insert_ordered_array((void*)head, &heap->index); insert_ordered_array((void*)head, &heap->index);
} else { } else {
header_t *head = lookup_ordered_array(idx, &heap->index); header_t *head = lookup_ordered_array(idx, &heap->index);
head->size += new_len - old_len; head->size += new_len - old_len;
// Update the footer // Update the footer
footer_t *foot = (footer_t*)((uint32_t)head + head->size - sizeof(footer_t)); footer_t *foot = (footer_t*)((uint32_t)head + head->size - sizeof(footer_t));
foot->header = head; foot->header = head;
foot->magic = HEAP_MAGIC; foot->magic = HEAP_MAGIC;
} }
// Now we have enough space, so recall this function again // Now we have enough space, so recall this function again
return alloc(size, page_align, heap); return alloc(size, page_align, heap);
} }
header_t *origin_hole_head = (header_t*)lookup_ordered_array(it, &heap->index); header_t *origin_hole_head = (header_t*)lookup_ordered_array(it, &heap->index);
uint32_t origin_hole_p = (uint32_t)origin_hole_head; uint32_t origin_hole_p = (uint32_t)origin_hole_head;
uint32_t origin_hole_s = origin_hole_head->size; uint32_t origin_hole_s = origin_hole_head->size;
// Check if we should split the hole into two parts // Check if we should split the hole into two parts
if(origin_hole_s-new_size < sizeof(header_t)+sizeof(footer_t)) { if(origin_hole_s-new_size < sizeof(header_t)+sizeof(footer_t)) {
// Increase the requested size to the size of the hole we found // Increase the requested size to the size of the hole we found
size += origin_hole_s-new_size; size += origin_hole_s-new_size;
new_size = origin_hole_s; new_size = origin_hole_s;
} }
// Check if we need to page-align data // Check if we need to page-align data
if(page_align && origin_hole_p&0xFFFFF000) { if(page_align && origin_hole_p&0xFFFFF000) {
uint32_t new_loc = origin_hole_p + 0x1000 - (origin_hole_p&0xFFF) - sizeof(header_t); uint32_t new_loc = origin_hole_p + 0x1000 - (origin_hole_p&0xFFF) - sizeof(header_t);
header_t *hole_header = (header_t*)origin_hole_p; header_t *hole_header = (header_t*)origin_hole_p;
hole_header->size = 0x1000 - (origin_hole_p&0xFFF) - sizeof(header_t); hole_header->size = 0x1000 - (origin_hole_p&0xFFF) - sizeof(header_t);
hole_header->magic = HEAP_MAGIC; hole_header->magic = HEAP_MAGIC;
hole_header->is_hole = 1; hole_header->is_hole = 1;
footer_t *hole_footer = (footer_t*)((uint32_t)new_loc - sizeof(header_t)); footer_t *hole_footer = (footer_t*)((uint32_t)new_loc - sizeof(header_t));
hole_footer->magic = HEAP_MAGIC; hole_footer->magic = HEAP_MAGIC;
hole_footer->header = hole_header; hole_footer->header = hole_header;
origin_hole_p = new_loc; origin_hole_p = new_loc;
origin_hole_s = origin_hole_s - hole_header->size; origin_hole_s = origin_hole_s - hole_header->size;
} else } else
remove_ordered_array(it, &heap->index); // Remove hole, since we don't need it anymore remove_ordered_array(it, &heap->index); // Remove hole, since we don't need it anymore
// Rewrite original header // Rewrite original header
header_t *block_head = (header_t*)origin_hole_p; header_t *block_head = (header_t*)origin_hole_p;
block_head->magic = HEAP_MAGIC; block_head->magic = HEAP_MAGIC;
block_head->is_hole = 0; block_head->is_hole = 0;
block_head->size = new_size; block_head->size = new_size;
// and the footer // and the footer
footer_t *block_foot = (footer_t*)(origin_hole_p + sizeof(header_t) + size); footer_t *block_foot = (footer_t*)(origin_hole_p + sizeof(header_t) + size);
block_foot->magic = HEAP_MAGIC; block_foot->magic = HEAP_MAGIC;
block_foot->header = block_head; block_foot->header = block_head;
// Check if we need to write a new hole after the allocated block // Check if we need to write a new hole after the allocated block
if(origin_hole_s - new_size > 0) { if(origin_hole_s - new_size > 0) {
header_t *hole_head = (header_t*)(origin_hole_p + sizeof(header_t) + size + sizeof(footer_t)); header_t *hole_head = (header_t*)(origin_hole_p + sizeof(header_t) + size + sizeof(footer_t));
hole_head->magic = HEAP_MAGIC; hole_head->magic = HEAP_MAGIC;
hole_head->is_hole = 1; hole_head->is_hole = 1;
hole_head->size = origin_hole_s - new_size; hole_head->size = origin_hole_s - new_size;
footer_t *hole_foot = (footer_t*)((uint32_t)hole_head + origin_hole_s - new_size - sizeof(footer_t)); footer_t *hole_foot = (footer_t*)((uint32_t)hole_head + origin_hole_s - new_size - sizeof(footer_t));
if((uint32_t)hole_foot < heap->end_address) { if((uint32_t)hole_foot < heap->end_address) {
hole_foot->magic = HEAP_MAGIC; hole_foot->magic = HEAP_MAGIC;
hole_foot->header = hole_head; hole_foot->header = hole_head;
} }
// Add new hole to the data structure // Add new hole to the data structure
insert_ordered_array((void*)hole_head, &heap->index); insert_ordered_array((void*)hole_head, &heap->index);
} }
// Return the block header // Return the block header
return (void*)((uint32_t)block_head+sizeof(header_t)); return (void*)((uint32_t)block_head+sizeof(header_t));
} }
void free(void *p, heap_t *heap) { void free(void *p, heap_t *heap) {
// Check null pointers // Check null pointers
if(p == 0) if(p == 0)
return; return;
// Retrieve data // Retrieve data
header_t *head = (header_t*)((uint32_t)p - sizeof(header_t)); header_t *head = (header_t*)((uint32_t)p - sizeof(header_t));
footer_t *foot = (footer_t*)((uint32_t)head + head->size - sizeof(footer_t)); footer_t *foot = (footer_t*)((uint32_t)head + head->size - sizeof(footer_t));
ASSERT(head->magic == HEAP_MAGIC); ASSERT(head->magic == HEAP_MAGIC);
ASSERT(foot->magic == HEAP_MAGIC); ASSERT(foot->magic == HEAP_MAGIC);
head->is_hole = 1; // Make this a hole head->is_hole = 1; // Make this a hole
int8_t add_to_free_hole = 1; // Add this header to free holes int8_t add_to_free_hole = 1; // Add this header to free holes
// Left unify // Left unify
footer_t *test_foot = (footer_t*)((uint32_t)head - sizeof(footer_t)); footer_t *test_foot = (footer_t*)((uint32_t)head - sizeof(footer_t));
if(test_foot->magic == HEAP_MAGIC && test_foot->header->is_hole == 1 ) { if(test_foot->magic == HEAP_MAGIC && test_foot->header->is_hole == 1 ) {
uint32_t cache_s = head->size; // Store current size uint32_t cache_s = head->size; // Store current size
head = test_foot->header; // Rewrite header into new one head = test_foot->header; // Rewrite header into new one
foot->header = head; // Point footer to the new header foot->header = head; // Point footer to the new header
head->size += cache_s; // Increase size head->size += cache_s; // Increase size
add_to_free_hole = 0; // Header already in the structure. add_to_free_hole = 0; // Header already in the structure.
} }
// Right unify // Right unify
header_t *test_head = (header_t*)((uint32_t)foot + sizeof(footer_t)); header_t *test_head = (header_t*)((uint32_t)foot + sizeof(footer_t));
if(test_head->magic == HEAP_MAGIC && test_head->is_hole) { if(test_head->magic == HEAP_MAGIC && test_head->is_hole) {
head->size += test_head->size; // Increase size head->size += test_head->size; // Increase size
test_foot = (footer_t*)((uint32_t)test_foot + test_head->size - sizeof(footer_t)); test_foot = (footer_t*)((uint32_t)test_foot + test_head->size - sizeof(footer_t));
foot = test_foot; foot = test_foot;
// Find and remove this header from the structure // Find and remove this header from the structure
uint32_t it = 0; uint32_t it = 0;
while((it < heap->index.size) && (lookup_ordered_array(it, &heap->index) != (void*)test_head)) while((it < heap->index.size) && (lookup_ordered_array(it, &heap->index) != (void*)test_head))
it++; it++;
// Check if we actually found something // Check if we actually found something
ASSERT(it < heap->index.size); ASSERT(it < heap->index.size);
// Remove that item // Remove that item
remove_ordered_array(it, &heap->index); remove_ordered_array(it, &heap->index);
} }
// If footer is located at the end, we can contract the heap // If footer is located at the end, we can contract the heap
if((uint32_t)foot+sizeof(footer_t) == heap->end_address) { if((uint32_t)foot+sizeof(footer_t) == heap->end_address) {
uint32_t old_len = heap->end_address-heap->start_address; uint32_t old_len = heap->end_address-heap->start_address;
uint32_t new_len = contract((uint32_t)head - heap->start_address, heap); uint32_t new_len = contract((uint32_t)head - heap->start_address, heap);
// Check dimensions after resizing // Check dimensions after resizing
if(head->size - (old_len-new_len) > 0) { if(head->size - (old_len-new_len) > 0) {
// Dimensions is still a positive value, so we can resize // Dimensions is still a positive value, so we can resize
head->size -= old_len-new_len; head->size -= old_len-new_len;
foot = (footer_t*)((uint32_t)head + head->size - sizeof(footer_t)); foot = (footer_t*)((uint32_t)head + head->size - sizeof(footer_t));
foot->magic = HEAP_MAGIC; foot->magic = HEAP_MAGIC;
foot->header = head; foot->header = head;
} else { } else {
// Remove block from the structure // Remove block from the structure
uint32_t it = 0; uint32_t it = 0;
while((it < heap->index.size) && (lookup_ordered_array(it, &heap->index) != (void*)test_head)) while((it < heap->index.size) && (lookup_ordered_array(it, &heap->index) != (void*)test_head))
it++; it++;
// If we didn't find that block we haven't nothing to remove // If we didn't find that block we haven't nothing to remove
if(it < heap->index.size) if(it < heap->index.size)
remove_ordered_array(it, &heap->index); remove_ordered_array(it, &heap->index);
} }
} }
// If required by the user, add that block to the structure // If required by the user, add that block to the structure
if(add_to_free_hole == 1) if(add_to_free_hole == 1)
insert_ordered_array((void*)head, &heap->index); insert_ordered_array((void*)head, &heap->index);
} }

View File

@ -1,70 +1,70 @@
/************************************** /*****************************************
* VulcanOS Kernel * * VulcanOS Kernel *
* Developed by Marco 'icebit' Cetica * * Developed by Marco 'icebit' Cetica *
* (c) 2019-2021 * * (c) 2019-2021 *
* Released under GPLv3 * * Released under GPLv3 *
* https://github.com/ice-bit/iceOS * * https://github.com/ice-bit/vulcanos *
***************************************/ *****************************************/
/*** Heap implementation from James Molloy's tutorial: /*** Heap implementation from James Molloy's tutorial:
http://www.jamesmolloy.co.uk/tutorial_html/7.-The%20Heap.html ***/ http://www.jamesmolloy.co.uk/tutorial_html/7.-The%20Heap.html ***/
/* This heap algorithm uses two different data structures: blocks and holes. /* This heap algorithm uses two different data structures: blocks and holes.
* Blocks: Contiguous areas of memory containing user data * Blocks: Contiguous areas of memory containing user data
* Holes: Special kind of blocks that are not in use, this is the result * Holes: Special kind of blocks that are not in use, this is the result
* of free() operation. Those spaces lend to a common problem called "Fragmentation"; * of free() operation. Those spaces lend to a common problem called "Fragmentation";
* where malloc() cannot use those spaces anymore because they are too small for any * where malloc() cannot use those spaces anymore because they are too small for any
* kind of program. Any modern OS must have a solution to avoid this problem, but to keep * kind of program. Any modern OS must have a solution to avoid this problem, but to keep
* things simple as possible i wont implement anything like that. * things simple as possible i wont implement anything like that.
* Blocks/holes contains informations like the magic number(error checking), the type of * Blocks/holes contains informations like the magic number(error checking), the type of
* chunk(hole or block) and the size, while the footer contains only a pointer to the header * chunk(hole or block) and the size, while the footer contains only a pointer to the header
* (and obviously an error checking flag). * (and obviously an error checking flag).
*/ */
#ifndef KHEAP_H #ifndef KHEAP_H
#define KHEAP_H #define KHEAP_H
#define KHEAP_START 0xC0000000 #define KHEAP_START 0xC0000000
#define KHEAP_INITIAL_SIZE 0x100000 #define KHEAP_INITIAL_SIZE 0x100000
#define HEAP_INDEX_SIZE 0x20000 #define HEAP_INDEX_SIZE 0x20000
#define HEAP_MAGIC 0x123890AB #define HEAP_MAGIC 0x123890AB
#define HEAP_MIN_SIZE 0x70000 #define HEAP_MIN_SIZE 0x70000
#include <stdint.h> #include <stdint.h>
#include "ordered_array.h" #include "ordered_array.h"
// Data structure for single hole/block // Data structure for single hole/block
typedef struct { typedef struct {
uint32_t magic; // Magic number for error checking uint32_t magic; // Magic number for error checking
uint8_t is_hole; // 1 if it's an hole, 0 for a block uint8_t is_hole; // 1 if it's an hole, 0 for a block
uint32_t size; // Size of block uint32_t size; // Size of block
} header_t; } header_t;
typedef struct { typedef struct {
uint32_t magic; // Same as above uint32_t magic; // Same as above
header_t *header; // Pointer to the header block header_t *header; // Pointer to the header block
} footer_t; } footer_t;
typedef struct { typedef struct {
ordered_array_t index; ordered_array_t index;
uint32_t start_address; // Begin of allocated space uint32_t start_address; // Begin of allocated space
uint32_t end_address; // End of allocated space uint32_t end_address; // End of allocated space
uint32_t max_address; // Maximum size heap can be expanded to uint32_t max_address; // Maximum size heap can be expanded to
uint8_t supervisor; uint8_t supervisor;
uint8_t readonly; uint8_t readonly;
} heap_t; } heap_t;
// Create a new heap // Create a new heap
heap_t *create_heap(uint32_t start, uint32_t end, uint32_t max, uint8_t supervisor, uint8_t readonly); heap_t *create_heap(uint32_t start, uint32_t end, uint32_t max, uint8_t supervisor, uint8_t readonly);
// Allocates a contigious region of memory in size // Allocates a contigious region of memory in size
void *alloc(uint32_t size, uint8_t page_align, heap_t *heap); void *alloc(uint32_t size, uint8_t page_align, heap_t *heap);
// Free a block allocated with alloc // Free a block allocated with alloc
void free(void *p, heap_t *heap); void free(void *p, heap_t *heap);
uint32_t kmalloc_int(uint32_t sz, int32_t align, uint32_t *phys); uint32_t kmalloc_int(uint32_t sz, int32_t align, uint32_t *phys);
uint32_t kmalloc_a(uint32_t sz); uint32_t kmalloc_a(uint32_t sz);
uint32_t kmalloc_p(uint32_t sz, uint32_t *phys); uint32_t kmalloc_p(uint32_t sz, uint32_t *phys);
uint32_t kmalloc_ap(uint32_t sz, uint32_t *phys); uint32_t kmalloc_ap(uint32_t sz, uint32_t *phys);
uint32_t kmalloc(uint32_t sz); uint32_t kmalloc(uint32_t sz);
void kfree(void *p); void kfree(void *p);
#endif #endif

File diff suppressed because it is too large Load Diff

View File

@ -1,66 +1,66 @@
#include "ordered_array.h" #include "ordered_array.h"
#include "kheap.h" #include "kheap.h"
#include "../libc/panic.h" #include "../libc/panic.h"
#include "../libc/string.h" #include "../libc/string.h"
uint8_t standard_lessthan_predicate(type_t a, type_t b) { uint8_t standard_lessthan_predicate(type_t a, type_t b) {
if (a < b) if (a < b)
return 1; return 1;
else else
return 0; return 0;
} }
ordered_array_t create_ordered_array(uint32_t max_size, lessthan_predicate_t less_than) { ordered_array_t create_ordered_array(uint32_t max_size, lessthan_predicate_t less_than) {
ordered_array_t to_ret; ordered_array_t to_ret;
to_ret.array = (void*)kmalloc(max_size*sizeof(type_t)); to_ret.array = (void*)kmalloc(max_size*sizeof(type_t));
memset(to_ret.array, 0, max_size*sizeof(type_t)); memset(to_ret.array, 0, max_size*sizeof(type_t));
to_ret.size = 0; to_ret.size = 0;
to_ret.max_size = max_size; to_ret.max_size = max_size;
to_ret.less_than = less_than; to_ret.less_than = less_than;
return to_ret; return to_ret;
} }
ordered_array_t place_ordered_array(void *addr, uint32_t max_size, lessthan_predicate_t less_than) { ordered_array_t place_ordered_array(void *addr, uint32_t max_size, lessthan_predicate_t less_than) {
ordered_array_t to_ret; ordered_array_t to_ret;
to_ret.array = (type_t*)addr; to_ret.array = (type_t*)addr;
memset(to_ret.array, 0, max_size*sizeof(type_t)); memset(to_ret.array, 0, max_size*sizeof(type_t));
to_ret.size = 0; to_ret.size = 0;
to_ret.max_size = max_size; to_ret.max_size = max_size;
to_ret.less_than = less_than; to_ret.less_than = less_than;
return to_ret; return to_ret;
} }
void destroy_ordered_array(ordered_array_t *array) { void destroy_ordered_array(ordered_array_t *array) {
kfree(array->array); kfree(array->array);
} }
void insert_ordered_array(type_t item, ordered_array_t *array) { void insert_ordered_array(type_t item, ordered_array_t *array) {
uint32_t it = 0; uint32_t it = 0;
while(it < array->size && array->less_than(array->array[it], item)) while(it < array->size && array->less_than(array->array[it], item))
it++; it++;
if(it == array->size) if(it == array->size)
array->array[array->size++] = item; array->array[array->size++] = item;
else { else {
type_t tmp = array->array[it]; type_t tmp = array->array[it];
array->array[it] = item; array->array[it] = item;
while(it < array->size) { while(it < array->size) {
it++; it++;
type_t tmp2 = array->array[it]; type_t tmp2 = array->array[it];
array->array[it] = tmp; array->array[it] = tmp;
tmp = tmp2; tmp = tmp2;
} }
array->size++; array->size++;
} }
} }
type_t lookup_ordered_array(uint32_t i, ordered_array_t *array) { type_t lookup_ordered_array(uint32_t i, ordered_array_t *array) {
return array->array[i]; return array->array[i];
} }
void remove_ordered_array(uint32_t i, ordered_array_t *array) { void remove_ordered_array(uint32_t i, ordered_array_t *array) {
while(i < array->size) { while(i < array->size) {
array->array[i] = array->array[i+1]; array->array[i] = array->array[i+1];
i++; i++;
} }
array->size--; array->size--;
} }

View File

@ -1,39 +1,39 @@
/************************************** /*****************************************
* VulcanOS Kernel * * VulcanOS Kernel *
* Developed by Marco 'icebit' Cetica * * Developed by Marco 'icebit' Cetica *
* (c) 2019-2021 * * (c) 2019-2021 *
* Released under GPLv3 * * Released under GPLv3 *
* https://github.com/ice-bit/iceOS * * https://github.com/ice-bit/vulcanos *
***************************************/ *****************************************/
#ifndef ORDERED_ARRAY_H #ifndef ORDERED_ARRAY_H
#define ORDERED_ARRAY_H #define ORDERED_ARRAY_H
#include <stdint.h> #include <stdint.h>
/* Our list is always in a 'sorted state', /* Our list is always in a 'sorted state',
* it can store anything that can be casted * it can store anything that can be casted
* to void* */ * to void* */
typedef void* type_t; typedef void* type_t;
/* The following predicate should return non-zero /* The following predicate should return non-zero
* if the first argument is less than the second */ * if the first argument is less than the second */
typedef uint8_t (*lessthan_predicate_t)(type_t,type_t); typedef uint8_t (*lessthan_predicate_t)(type_t,type_t);
typedef struct { typedef struct {
type_t *array; type_t *array;
uint32_t size; uint32_t size;
uint32_t max_size; uint32_t max_size;
lessthan_predicate_t less_than; lessthan_predicate_t less_than;
} ordered_array_t; } ordered_array_t;
uint8_t standard_lessthan_predicate(type_t a, type_t b); uint8_t standard_lessthan_predicate(type_t a, type_t b);
// Create a new ordered array // Create a new ordered array
ordered_array_t create_ordered_array(uint32_t max_size, lessthan_predicate_t less_than); ordered_array_t create_ordered_array(uint32_t max_size, lessthan_predicate_t less_than);
ordered_array_t place_ordered_array(void *addr, uint32_t max_size, lessthan_predicate_t less_than); ordered_array_t place_ordered_array(void *addr, uint32_t max_size, lessthan_predicate_t less_than);
// Destroy an ordered array // Destroy an ordered array
void destroy_ordered_array(ordered_array_t *array); void destroy_ordered_array(ordered_array_t *array);
// Add an item into the array // Add an item into the array
void insert_ordered_array(type_t item, ordered_array_t *array); void insert_ordered_array(type_t item, ordered_array_t *array);
type_t lookup_ordered_array(uint32_t i, ordered_array_t *array); type_t lookup_ordered_array(uint32_t i, ordered_array_t *array);
void remove_ordered_array(uint32_t i, ordered_array_t *array); void remove_ordered_array(uint32_t i, ordered_array_t *array);
#endif #endif

View File

@ -1,141 +1,141 @@
#include "paging.h" #include "paging.h"
#include "../libc/string.h" #include "../libc/string.h"
#include "../libc/panic.h" #include "../libc/panic.h"
#include "../libc/stdio.h" #include "../libc/stdio.h"
#include "../drivers/tty.h" #include "../drivers/tty.h"
// External definitions from kheap.c // External definitions from kheap.c
extern uint32_t placement_addr; extern uint32_t placement_addr;
extern heap_t *kheap; extern heap_t *kheap;
// Bitset of frames, used or free // Bitset of frames, used or free
uint32_t *frame_allocations; uint32_t *frame_allocations;
uint32_t nframes; // Number of physical frames uint32_t nframes; // Number of physical frames
page_directory_t *kernel_directory = 0; page_directory_t *kernel_directory = 0;
page_directory_t *current_directory = 0; page_directory_t *current_directory = 0;
static void set_frame(uint32_t addr) { static void set_frame(uint32_t addr) {
uint32_t frame = FRAME(addr); uint32_t frame = FRAME(addr);
uint32_t frame_alloc_s = FRAME_SECTION(frame); uint32_t frame_alloc_s = FRAME_SECTION(frame);
uint32_t frame_alloc_o = FRAME_OFFSET(frame); uint32_t frame_alloc_o = FRAME_OFFSET(frame);
frame_allocations[frame_alloc_s] |= (1 << frame_alloc_o); frame_allocations[frame_alloc_s] |= (1 << frame_alloc_o);
} }
static void clear_frame(uint32_t addr) { static void clear_frame(uint32_t addr) {
uint32_t frame = FRAME(addr); uint32_t frame = FRAME(addr);
uint32_t frame_alloc_s = FRAME_SECTION(frame); uint32_t frame_alloc_s = FRAME_SECTION(frame);
uint32_t frame_alloc_o = FRAME_OFFSET(frame); uint32_t frame_alloc_o = FRAME_OFFSET(frame);
frame_allocations[frame_alloc_s] &= ~(1 << frame_alloc_o); frame_allocations[frame_alloc_s] &= ~(1 << frame_alloc_o);
} }
static uint32_t first_frame() { static uint32_t first_frame() {
uint32_t nsections = nframes / FRAME_ALLOCATIONS_SECTION_SIZE; uint32_t nsections = nframes / FRAME_ALLOCATIONS_SECTION_SIZE;
for(uint32_t sec = 0; sec < nsections; sec++) for(uint32_t sec = 0; sec < nsections; sec++)
if(frame_allocations[sec] != USED_FRAME_SECTION) if(frame_allocations[sec] != USED_FRAME_SECTION)
for(uint32_t idx = 0; idx < FRAME_ALLOCATIONS_SECTION_SIZE; idx++) for(uint32_t idx = 0; idx < FRAME_ALLOCATIONS_SECTION_SIZE; idx++)
if(!(frame_allocations[sec] & (0x1 << idx))) if(!(frame_allocations[sec] & (0x1 << idx)))
return (sec*FRAME_ALLOCATIONS_SECTION_SIZE) + idx; return (sec*FRAME_ALLOCATIONS_SECTION_SIZE) + idx;
return nsections * FRAME_ALLOCATIONS_SECTION_SIZE; return nsections * FRAME_ALLOCATIONS_SECTION_SIZE;
} }
void alloc_frame(page_t *page, int32_t is_super, int32_t is_write) { void alloc_frame(page_t *page, int32_t is_super, int32_t is_write) {
if(page->fr != 0) if(page->fr != 0)
return; return;
else { else {
uint32_t fframe = first_frame(); uint32_t fframe = first_frame();
if(fframe == (uint32_t)-1) { if(fframe == (uint32_t)-1) {
PANIC("No free frames availables!"); PANIC("No free frames availables!");
} else { } else {
// Set free frames to the page // Set free frames to the page
page->pr = PAGE_PRESENT; page->pr = PAGE_PRESENT;
page->rw = (is_write) ? PAGE_READ_WRITE : PAGE_READ_ONLY; page->rw = (is_write) ? PAGE_READ_WRITE : PAGE_READ_ONLY;
page->us = (is_super) ? PAGE_SUPERVISOR : PAGE_USER; page->us = (is_super) ? PAGE_SUPERVISOR : PAGE_USER;
page->fr = fframe; page->fr = fframe;
// Set new frames as used // Set new frames as used
uint32_t physical_addr = fframe * FRAME_SIZE; uint32_t physical_addr = fframe * FRAME_SIZE;
set_frame(physical_addr); set_frame(physical_addr);
} }
} }
} }
void free_frame(page_t *page) { void free_frame(page_t *page) {
uint32_t frame; uint32_t frame;
if(!(frame=page->fr)) if(!(frame=page->fr))
return; // page doesn't have a frame in first place return; // page doesn't have a frame in first place
else { else {
clear_frame(frame); clear_frame(frame);
page->fr = 0x0; page->fr = 0x0;
} }
} }
void init_paging() { void init_paging() {
// Setup frame allocation // Setup frame allocation
nframes = PHYSICAL_MEM_SIZE / FRAME_SIZE; nframes = PHYSICAL_MEM_SIZE / FRAME_SIZE;
frame_allocations = (uint32_t*)kmalloc(nframes/FRAME_ALLOCATIONS_SECTION_SIZE); frame_allocations = (uint32_t*)kmalloc(nframes/FRAME_ALLOCATIONS_SECTION_SIZE);
memset(frame_allocations, 0, nframes/FRAME_ALLOCATIONS_SECTION_SIZE); memset(frame_allocations, 0, nframes/FRAME_ALLOCATIONS_SECTION_SIZE);
// Setup page directory // Setup page directory
kernel_directory = (page_directory_t*)kmalloc_a(sizeof(page_directory_t)); kernel_directory = (page_directory_t*)kmalloc_a(sizeof(page_directory_t));
memset(kernel_directory, 0, sizeof(page_directory_t)); memset(kernel_directory, 0, sizeof(page_directory_t));
current_directory = kernel_directory; current_directory = kernel_directory;
// Map heap pages // Map heap pages
for(uint32_t i = KHEAP_START; i < KHEAP_START + KHEAP_INITIAL_SIZE; i += FRAME_SIZE) for(uint32_t i = KHEAP_START; i < KHEAP_START + KHEAP_INITIAL_SIZE; i += FRAME_SIZE)
get_page(i, 1, kernel_directory); get_page(i, 1, kernel_directory);
// Setup identity map // Setup identity map
for(uint32_t i = 0; i < placement_addr + FRAME_SIZE; i += FRAME_SIZE) for(uint32_t i = 0; i < placement_addr + FRAME_SIZE; i += FRAME_SIZE)
alloc_frame(get_page(i, 1, kernel_directory), 0, 0); alloc_frame(get_page(i, 1, kernel_directory), 0, 0);
// Allocate heap pages // Allocate heap pages
for(uint32_t i = KHEAP_START; i < KHEAP_START+KHEAP_INITIAL_SIZE; i += FRAME_SIZE) for(uint32_t i = KHEAP_START; i < KHEAP_START+KHEAP_INITIAL_SIZE; i += FRAME_SIZE)
alloc_frame(get_page(i, 1, kernel_directory), 0, 0); alloc_frame(get_page(i, 1, kernel_directory), 0, 0);
// Register a new ISR to listen to IRQ 14 // Register a new ISR to listen to IRQ 14
register_interrupt_handler(14, page_fault); register_interrupt_handler(14, page_fault);
enable_paging(kernel_directory); enable_paging(kernel_directory);
kheap = create_heap(KHEAP_START, KHEAP_START+KHEAP_INITIAL_SIZE, 0xCFFFF000, 0, 0); kheap = create_heap(KHEAP_START, KHEAP_START+KHEAP_INITIAL_SIZE, 0xCFFFF000, 0, 0);
} }
void enable_paging(page_directory_t *dir) { void enable_paging(page_directory_t *dir) {
current_directory = dir; current_directory = dir;
asm volatile("mov %0, %%cr3" :: "r"(&dir->page_tables_physical)); asm volatile("mov %0, %%cr3" :: "r"(&dir->page_tables_physical));
uint32_t cr0; uint32_t cr0;
asm volatile("mov %%cr0, %0" : "=r"(cr0)); asm volatile("mov %%cr0, %0" : "=r"(cr0));
cr0 |= 0x80000000; // Correct code to enable paging cr0 |= 0x80000000; // Correct code to enable paging
asm volatile("mov %0, %%cr0" :: "r"(cr0)); asm volatile("mov %0, %%cr0" :: "r"(cr0));
} }
page_t *get_page(uint32_t address, int32_t make, page_directory_t *dir) { page_t *get_page(uint32_t address, int32_t make, page_directory_t *dir) {
address /= 0x1000; // turn address into an index address /= 0x1000; // turn address into an index
uint32_t table_idx = address / 1024; // Find page that contains the address uint32_t table_idx = address / 1024; // Find page that contains the address
if(dir->page_tables_virtual[table_idx]) if(dir->page_tables_virtual[table_idx])
return &dir->page_tables_virtual[table_idx]->pages[address%1024]; return &dir->page_tables_virtual[table_idx]->pages[address%1024];
else if(make) { else if(make) {
uint32_t tmp; uint32_t tmp;
dir->page_tables_virtual[table_idx] = (page_table_t*)kmalloc_ap(sizeof(page_table_t), &tmp); dir->page_tables_virtual[table_idx] = (page_table_t*)kmalloc_ap(sizeof(page_table_t), &tmp);
memset(dir->page_tables_virtual[table_idx], 0, 0x1000); memset(dir->page_tables_virtual[table_idx], 0, 0x1000);
dir->page_tables_physical[table_idx] = tmp | 0x7; dir->page_tables_physical[table_idx] = tmp | 0x7;
return &dir->page_tables_virtual[table_idx]->pages[address%1024]; return &dir->page_tables_virtual[table_idx]->pages[address%1024];
} else } else
return 0; return 0;
} }
void page_fault(registers_t regs) { void page_fault(registers_t regs) {
// Handle a page fault // Handle a page fault
uint32_t faulting_addr; uint32_t faulting_addr;
asm volatile("mov %%cr2, %0" : "=r" (faulting_addr)); asm volatile("mov %%cr2, %0" : "=r" (faulting_addr));
// Gracefully print the error // Gracefully print the error
kprint((uint8_t*)"\nPage fault! ( "); kprint((uint8_t*)"\nPage fault! ( ");
if(!(regs.err_code & 0x1)) if(!(regs.err_code & 0x1))
kprint((uint8_t*)"Present "); kprint((uint8_t*)"Present ");
if(regs.err_code & 0x2) if(regs.err_code & 0x2)
kprint((uint8_t*)"Read-Only "); kprint((uint8_t*)"Read-Only ");
if(regs.err_code & 0x4) if(regs.err_code & 0x4)
kprint((uint8_t*)"User-Mode "); kprint((uint8_t*)"User-Mode ");
if(regs.err_code & 0x8) if(regs.err_code & 0x8)
kprint((uint8_t*)"Reserved"); kprint((uint8_t*)"Reserved");
printf(") at %x\n", faulting_addr); printf(") at %x\n", faulting_addr);
PANIC("Page fault"); PANIC("Page fault");
} }

View File

@ -1,81 +1,81 @@
/************************************** /*****************************************
* VulcanOS Kernel * * VulcanOS Kernel *
* Developed by Marco 'icebit' Cetica * * Developed by Marco 'icebit' Cetica *
* (c) 2019-2021 * * (c) 2019-2021 *
* Released under GPLv3 * * Released under GPLv3 *
* https://github.com/ice-bit/iceOS * * https://github.com/ice-bit/vulcanos *
***************************************/ *****************************************/
#ifndef PAGING_H #ifndef PAGING_H
#define PAGING_H #define PAGING_H
#include <stdint.h> #include <stdint.h>
#include "../drivers/isr.h" #include "../drivers/isr.h"
#include "kheap.h" #include "kheap.h"
#define FRAME_SIZE 4096 #define FRAME_SIZE 4096
#define PAGE_TABLE_SIZE 1024 #define PAGE_TABLE_SIZE 1024
#define PAGE_DIRECTORY_SIZE 1024 #define PAGE_DIRECTORY_SIZE 1024
#define PAGE_NOT_PRESENT 0 #define PAGE_NOT_PRESENT 0
#define PAGE_PRESENT 1 #define PAGE_PRESENT 1
#define PAGE_READ_ONLY 0 #define PAGE_READ_ONLY 0
#define PAGE_READ_WRITE 1 #define PAGE_READ_WRITE 1
#define PAGE_USER 0 #define PAGE_USER 0
#define PAGE_SUPERVISOR 0 #define PAGE_SUPERVISOR 0
#define PAGE_SIZE_4KB 0 #define PAGE_SIZE_4KB 0
#define PAGE_SIZE_4MB 1 #define PAGE_SIZE_4MB 1
// Frames macros // Frames macros
#define FRAME_ALLOCATIONS_SECTION_SIZE 32 #define FRAME_ALLOCATIONS_SECTION_SIZE 32
#define USED_FRAME_SECTION 0xFFFFFFFF #define USED_FRAME_SECTION 0xFFFFFFFF
#define FREE_FRAME_SECTION 0x00000000 #define FREE_FRAME_SECTION 0x00000000
#define FRAME(addr) (addr/FRAME_SIZE) #define FRAME(addr) (addr/FRAME_SIZE)
#define FRAME_SECTION(frame) (frame/FRAME_ALLOCATIONS_SECTION_SIZE) #define FRAME_SECTION(frame) (frame/FRAME_ALLOCATIONS_SECTION_SIZE)
#define FRAME_OFFSET(frame) (frame%FRAME_ALLOCATIONS_SECTION_SIZE) #define FRAME_OFFSET(frame) (frame%FRAME_ALLOCATIONS_SECTION_SIZE)
// Set physical memory to 15 MiB // Set physical memory to 15 MiB
#define PHYSICAL_MEM_SIZE 0x10000000 #define PHYSICAL_MEM_SIZE 0x10000000
struct page { // Single page structure, from intel's developer manual struct page { // Single page structure, from intel's developer manual
uint8_t pr : 1; // Present: 1 to map 4KB page uint8_t pr : 1; // Present: 1 to map 4KB page
uint8_t rw : 1; // Read/Write mode uint8_t rw : 1; // Read/Write mode
uint8_t us : 1; // if 0, user mode access aren't allowed to the page uint8_t us : 1; // if 0, user mode access aren't allowed to the page
uint8_t pw : 1; // Page-level write through uint8_t pw : 1; // Page-level write through
uint8_t pc : 1; // Page-level cache disable uint8_t pc : 1; // Page-level cache disable
uint8_t ac : 1; // 1 if we have accessed 4kb page uint8_t ac : 1; // 1 if we have accessed 4kb page
uint8_t di : 1; // 1 if page has been written(dirty) uint8_t di : 1; // 1 if page has been written(dirty)
uint8_t pa : 1; // Unused bit uint8_t pa : 1; // Unused bit
uint8_t gl : 1; // 1 if page is global uint8_t gl : 1; // 1 if page is global
uint8_t ig : 3; // Unused bit uint8_t ig : 3; // Unused bit
uint32_t fr: 20; // Physical address of frame uint32_t fr: 20; // Physical address of frame
} __attribute__((packed)); } __attribute__((packed));
typedef struct page page_t; typedef struct page page_t;
typedef struct page_table { typedef struct page_table {
page_t pages[PAGE_TABLE_SIZE]; page_t pages[PAGE_TABLE_SIZE];
} page_table_t; } page_table_t;
/* Holds 2 arrays for each page directory /* Holds 2 arrays for each page directory
* one holds the physical address, while * one holds the physical address, while
* the other one holds the virtual address * the other one holds the virtual address
* (to write/read to it) */ * (to write/read to it) */
typedef struct page_directory { typedef struct page_directory {
page_table_t *page_tables_virtual[PAGE_DIRECTORY_SIZE]; page_table_t *page_tables_virtual[PAGE_DIRECTORY_SIZE];
uint32_t page_tables_physical[PAGE_DIRECTORY_SIZE]; uint32_t page_tables_physical[PAGE_DIRECTORY_SIZE];
} page_directory_t; } page_directory_t;
// Setup environment, page directories and enable paging // Setup environment, page directories and enable paging
void init_paging(); void init_paging();
// Perform the "enable-paging" operation to the right register // Perform the "enable-paging" operation to the right register
void enable_paging(page_directory_t *dir); void enable_paging(page_directory_t *dir);
// Retrieve a pointer from the given page // Retrieve a pointer from the given page
page_t *get_page(uint32_t address, int32_t make, page_directory_t *dir); page_t *get_page(uint32_t address, int32_t make, page_directory_t *dir);
// Identity map(phys = virtual addr) to access it as if paging wasn't enabled // Identity map(phys = virtual addr) to access it as if paging wasn't enabled
void identity_map(); void identity_map();
// Delete a frame // Delete a frame
void free_frame(page_t *page); void free_frame(page_t *page);
// Allocate a new frame // Allocate a new frame
void alloc_frame(page_t *page, int32_t is_super, int32_t is_write); void alloc_frame(page_t *page, int32_t is_super, int32_t is_write);
// Page faults handler(ISR recorder) // Page faults handler(ISR recorder)
void page_fault(registers_t regs); void page_fault(registers_t regs);
#endif #endif

View File

@ -1,10 +1,10 @@
OBJS = shell.o fetch.o OBJS = shell.o fetch.o
VER := $(shell git rev-parse --short HEAD) VER := $(shell git rev-parse --short HEAD)
CC = i686-elf-gcc # cross-compiler CC = i686-elf-gcc # cross-compiler
CFLAGS = -DDEFAULT_USER=root -DDEFAULT_HOSTNAME=vulcan -DVULCAN_VERSION=$(VER) -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 %.o: %.c
$(CC) $(CFLAGS) $< -o $@ $(CC) $(CFLAGS) $< -o $@

View File

@ -1,75 +1,75 @@
#include "fetch.h" #include "fetch.h"
#include "../libc/stdio.h" #include "../libc/stdio.h"
#include "../libc/string.h" #include "../libc/string.h"
#include "../libc/time.h" #include "../libc/time.h"
#include "../drivers/tty.h" #include "../drivers/tty.h"
#include "../drivers/cpuid.h" #include "../drivers/cpuid.h"
#define STRINGIZE(x) #x #define STRINGIZE(x) #x
#define STRINGIZE_VALUE_OF(x) STRINGIZE(x) #define STRINGIZE_VALUE_OF(x) STRINGIZE(x)
static void get_date(); static void get_date();
static void get_cpuid(); static void get_cpuid();
static void get_version(); static void get_version();
void system_fetcher() { void system_fetcher() {
uint8_t user[64], hostname[64]; uint8_t user[64], hostname[64];
#ifdef DEFAULT_USER #ifdef DEFAULT_USER
strcpy(user, (uint8_t*)STRINGIZE_VALUE_OF(DEFAULT_USER)); strcpy(user, (uint8_t*)STRINGIZE_VALUE_OF(DEFAULT_USER));
#else #else
#error "-DDEFAULT_USER flag not set" #error "-DDEFAULT_USER flag not set"
#endif #endif
#ifdef DEFAULT_HOSTNAME #ifdef DEFAULT_HOSTNAME
strcpy(hostname, (uint8_t*)STRINGIZE_VALUE_OF(DEFAULT_HOSTNAME)); strcpy(hostname, (uint8_t*)STRINGIZE_VALUE_OF(DEFAULT_HOSTNAME));
#else #else
#error "-DDEFAULT_HOSTNAME flag not set" #error "-DDEFAULT_HOSTNAME flag not set"
#endif #endif
// print first line // print first line
printf_color("\n __ __ ___ ___ ", LIGHT_RED, BLACK); printf_color("\n __ __ ___ ___ ", LIGHT_RED, BLACK);
printf_color((char*)user, LIGHT_CYAN, BLACK); printf_color((char*)user, LIGHT_CYAN, BLACK);
printf_color("@", LIGHT_RED, BLACK); printf_color("@", LIGHT_RED, BLACK);
printf_color((char*)hostname, LIGHT_CYAN, BLACK); printf_color((char*)hostname, LIGHT_CYAN, BLACK);
// print second line // print second line
printf_color("\n \\ \\ / / / _ \\/ __| ", LIGHT_RED, BLACK); printf_color("\n \\ \\ / / / _ \\/ __| ", LIGHT_RED, BLACK);
printf_color("-----------", LIGHT_RED, BLACK); printf_color("-----------", LIGHT_RED, BLACK);
// print third line // print third line
printf_color("\n \\ V / | (_) \\__ \\ ", LIGHT_RED, BLACK); printf_color("\n \\ V / | (_) \\__ \\ ", LIGHT_RED, BLACK);
printf_color("Date: ", LIGHT_CYAN, BLACK); printf_color("Date: ", LIGHT_CYAN, BLACK);
get_date(); get_date();
// print fourth line // print fourth line
printf_color("\n \\_/ \\___/|___/ ", LIGHT_RED, BLACK); printf_color("\n \\_/ \\___/|___/ ", LIGHT_RED, BLACK);
get_cpuid(); get_cpuid();
// print VulcanOS version // print VulcanOS version
get_version(); get_version();
} }
// Date format is D/M/YY // Date format is D/M/YY
void get_date() { void get_date() {
printf("%d", get_time(TIME_R_DAY)); // Day printf("%d", get_time(TIME_R_DAY)); // Day
printf_color("/", LIGHT_BLUE, BLACK); printf_color("/", LIGHT_BLUE, BLACK);
printf("%d", get_time(TIME_R_MONTH)); // Month printf("%d", get_time(TIME_R_MONTH)); // Month
printf_color("/", LIGHT_BLUE, BLACK); printf_color("/", LIGHT_BLUE, BLACK);
printf("%d", get_time(TIME_R_YEAR)); // Year printf("%d", get_time(TIME_R_YEAR)); // Year
} }
void get_cpuid() { void get_cpuid() {
printf_color("CPU type: ", LIGHT_CYAN, BLACK); printf_color("CPU type: ", LIGHT_CYAN, BLACK);
printf("%s", (char*)get_cpu_type()); // Print CPU type printf("%s", (char*)get_cpu_type()); // Print CPU type
printf("%s%s%c", " (", (char*)get_cpu_family(), ')'); printf("%s%s%c", " (", (char*)get_cpu_family(), ')');
} }
void get_version() { void get_version() {
uint8_t version[64]; uint8_t version[64];
#ifdef VULCAN_VERSION #ifdef VULCAN_VERSION
strcpy(version, (uint8_t*)STRINGIZE_VALUE_OF(VULCAN_VERSION)); strcpy(version, (uint8_t*)STRINGIZE_VALUE_OF(VULCAN_VERSION));
#else #else
#error "-DVULCAN_VERSION flag not set" #error "-DVULCAN_VERSION flag not set"
#endif #endif
printf_color("\n\t\t\t\t\t Version: ", LIGHT_CYAN, BLACK); printf_color("\n\t\t\t\t\t Version: ", LIGHT_CYAN, BLACK);
printf_color((char*)version, LIGHT_GREEN, BLACK); printf_color((char*)version, LIGHT_GREEN, BLACK);
} }

View File

@ -1,15 +1,15 @@
/************************************** /**************************************
* VulcanOS Kernel * * VulcanOS Kernel *
* Developed by Marco 'icebit' Cetica * * Developed by Marco 'icebit' Cetica *
* (c) 2019-2021 * * (c) 2019-2021 *
* Released under GPLv3 * * Released under GPLv3 *
* https://github.com/ice-bit/iceOS * * https://github.com/ice-bit/iceOS *
***************************************/ ***************************************/
#ifndef FETCH_H #ifndef FETCH_H
#define FETCH_H #define FETCH_H
#include <stdint.h> #include <stdint.h>
void system_fetcher(); void system_fetcher();
#endif #endif

View File

@ -1,122 +1,122 @@
#include "shell.h" #include "shell.h"
#include "fetch.h" #include "fetch.h"
#include "../libc/string.h" #include "../libc/string.h"
#include "../libc/stdio.h" #include "../libc/stdio.h"
#include "../drivers/tty.h" #include "../drivers/tty.h"
#include "../drivers/ports.h" #include "../drivers/ports.h"
#include "../drivers/timer.h" #include "../drivers/timer.h"
void helper() { void helper() {
puts("\nList of available commands:\n" puts("\nList of available commands:\n"
"\nhelp - Print this helper" "\nhelp - Print this helper"
"\nint - Test some interrupts" "\nint - Test some interrupts"
"\nbanner - Show banner" "\nbanner - Show banner"
"\nclear, cls - Clear the screen" "\nclear, cls - Clear the screen"
"\nregs - Prints register dump" "\nregs - Prints register dump"
"\ntimer - Prints timer tick" "\ntimer - Prints timer tick"
"\nabout - About this kernel" "\nabout - About this kernel"
"\nreboot - Reboot the system" "\nreboot - Reboot the system"
); );
} }
void test_interrupts() { void test_interrupts() {
// Testing some interrupts // Testing some interrupts
asm("int $0"); // Division by zero asm("int $0"); // Division by zero
asm("int $4"); // Stack overflow asm("int $4"); // Stack overflow
asm("int $1"); // Page fault asm("int $1"); // Page fault
} }
void about() { void about() {
printf_color("\n====== IceOS v0.0.1 (c) 2019 Marco 'icebit' Cetica ======\n\n", printf_color("\n====== IceOS v0.0.1 (c) 2019 Marco 'icebit' Cetica ======\n\n",
LIGHT_CYAN, BLACK); LIGHT_CYAN, BLACK);
printf_color( printf_color(
"iceOS is a x86 monolithic kernel written in C from scratch.\n" "iceOS is a x86 monolithic kernel written in C from scratch.\n"
"This project doesn't aim to be a fully functional operating system\n" "This project doesn't aim to be a fully functional operating system\n"
"with tons of drivers and graphical applications,\nit's just a learning tool " "with tons of drivers and graphical applications,\nit's just a learning tool "
"to teach myself concepts like\nOperating Systems, Computer Architecture and Digital Electronics.\n" "to teach myself concepts like\nOperating Systems, Computer Architecture and Digital Electronics.\n"
"\n\n" "\n\n"
"iceOS comes with the following features:\n" "iceOS comes with the following features:\n"
"- Bare metal booting;\n" "- Bare metal booting;\n"
"- VGA driver;\n" "- VGA driver;\n"
"- Interrupts implementation;\n" "- Interrupts implementation;\n"
"- PIC & PIT implementation;\n" "- PIC & PIT implementation;\n"
"- PS2 driver;\n" "- PS2 driver;\n"
"- Support for x86 architecture;\n" "- Support for x86 architecture;\n"
"- GRUB as bootloader;\n", "- GRUB as bootloader;\n",
LIGHT_GREEN, BLACK); LIGHT_GREEN, BLACK);
} }
void register_dump() { void register_dump() {
register uint32_t eax_v asm("eax"); register uint32_t eax_v asm("eax");
register uint32_t ebx_v asm("ebx"); register uint32_t ebx_v asm("ebx");
register uint32_t ecx_v asm("ecx"); register uint32_t ecx_v asm("ecx");
register uint32_t edx_v asm("edx"); register uint32_t edx_v asm("edx");
register uint32_t esx_v asm("esi"); register uint32_t esx_v asm("esi");
register uint32_t edi_v asm("edi"); register uint32_t edi_v asm("edi");
register uint32_t ebp_v asm("ebp"); register uint32_t ebp_v asm("ebp");
register uint32_t esp_v asm("esp"); register uint32_t esp_v asm("esp");
printf_color("\n===================================\n" printf_color("\n===================================\n"
" BEGIN 32 BITS CPU REGISTER DUMP \n" " BEGIN 32 BITS CPU REGISTER DUMP \n"
"===================================\n", "===================================\n",
LIGHT_BROWN, BLACK); LIGHT_BROWN, BLACK);
printf(" EAX: %x\n" printf(" EAX: %x\n"
" EBX: %x\n" " EBX: %x\n"
" ECX: %x\n" " ECX: %x\n"
" EDX: %x\n" " EDX: %x\n"
" ESX: %x\n" " ESX: %x\n"
" EDI: %x\n" " EDI: %x\n"
" EBP: %x\n" " EBP: %x\n"
" ESP: %x\n", " ESP: %x\n",
eax_v, ebx_v, ecx_v, edx_v, esx_v, edi_v, ebp_v, esp_v); eax_v, ebx_v, ecx_v, edx_v, esx_v, edi_v, ebp_v, esp_v);
printf_color("\n==================================\n" printf_color("\n==================================\n"
" END 32 BITS CPU REGISTER DUMP \n" " END 32 BITS CPU REGISTER DUMP \n"
"==================================\n", "==================================\n",
LIGHT_BROWN, BLACK); LIGHT_BROWN, BLACK);
} }
void timer_dump() { void timer_dump() {
uint8_t buf[8]; uint8_t buf[8];
uitoa(tick, buf, 10); uitoa(tick, buf, 10);
printf_color("\nTicks since boot: ", printf_color("\nTicks since boot: ",
LIGHT_GREEN, BLACK); LIGHT_GREEN, BLACK);
printf_color((const char*)buf, printf_color((const char*)buf,
LIGHT_CYAN, BLACK); LIGHT_CYAN, BLACK);
} }
void reboot() { void reboot() {
uint8_t tmp; uint8_t tmp;
asm("cli"); // First disable all interrupts asm("cli"); // First disable all interrupts
// Clear keyboard buffers // Clear keyboard buffers
do { do {
tmp = inb(0x64); // Keyboard interface tmp = inb(0x64); // Keyboard interface
if(check_flag(tmp, 0) != 0) if(check_flag(tmp, 0) != 0)
inb(0x60); // Clear keyboard data inb(0x60); // Clear keyboard data
} while(check_flag(tmp, 1) != 0); } while(check_flag(tmp, 1) != 0);
outb(0x64, 0xFE); // Reset the CPU outb(0x64, 0xFE); // Reset the CPU
} }
void processCommand(uint8_t *cmd) { void processCommand(uint8_t *cmd) {
if(strcmp(cmd, (uint8_t*)"help") == 0) if(strcmp(cmd, (uint8_t*)"help") == 0)
helper(); helper();
else if(strcmp(cmd, (uint8_t*)"int") == 0) else if(strcmp(cmd, (uint8_t*)"int") == 0)
test_interrupts(); test_interrupts();
else if(strcmp(cmd, (uint8_t*)"clear") == 0 || strcmp(cmd, (uint8_t*)"cls") == 0) else if(strcmp(cmd, (uint8_t*)"clear") == 0 || strcmp(cmd, (uint8_t*)"cls") == 0)
clear_prompt(); clear_prompt();
else if(strcmp(cmd, (uint8_t*)"about") == 0) else if(strcmp(cmd, (uint8_t*)"about") == 0)
about(); about();
else if(strcmp(cmd, (uint8_t*)"regs") == 0) else if(strcmp(cmd, (uint8_t*)"regs") == 0)
register_dump(); register_dump();
else if(strcmp(cmd, (uint8_t*)"timer") == 0) else if(strcmp(cmd, (uint8_t*)"timer") == 0)
timer_dump(); timer_dump();
else if(strcmp(cmd, (uint8_t*)"fetch") == 0) else if(strcmp(cmd, (uint8_t*)"fetch") == 0)
system_fetcher(); system_fetcher();
else if(strcmp(cmd, (uint8_t*)"reboot") == 0) else if(strcmp(cmd, (uint8_t*)"reboot") == 0)
reboot(); reboot();
else if(strcmp(cmd, (uint8_t*)"") == 0) else if(strcmp(cmd, (uint8_t*)"") == 0)
puts(""); puts("");
else else
puts("\nCommand not found!"); puts("\nCommand not found!");
} }

View File

@ -1,19 +1,19 @@
/************************************** /**************************************
* VulcanOS Kernel * * VulcanOS Kernel *
* Developed by Marco 'icebit' Cetica * * Developed by Marco 'icebit' Cetica *
* (c) 2019-2021 * * (c) 2019-2021 *
* Released under GPLv3 * * Released under GPLv3 *
* https://github.com/ice-bit/iceOS * * https://github.com/ice-bit/iceOS *
***************************************/ ***************************************/
#ifndef _SHELL_H_ #ifndef _SHELL_H_
#define _SHELL_H_ #define _SHELL_H_
#include <stdint.h> #include <stdint.h>
#define bit(n) (1 << (n)) #define bit(n) (1 << (n))
#define check_flag(flags, n) ((flags) & bit(n)) #define check_flag(flags, n) ((flags) & bit(n))
void helper(); void helper();
void processCommand(uint8_t *cmd); void processCommand(uint8_t *cmd);
#endif #endif

55
link.ld
View File

@ -1,28 +1,27 @@
ENTRY(kernel_loader) ENTRY(kernel_loader)
SECTIONS
{ SECTIONS
{
.text 0x100000 : . = 1M;
{
code = .; _code = .; __code = .; .boot :
*(.text) {
. = ALIGN(4096); KEEP(*(.multiboot_header))
} . = ALIGN(4096);
}
.data :
{ .text :
data = .; _data = .; __data = .; {
*(.data) *(.data)
*(.rodata) *(.rodata)
. = ALIGN(4096); . = ALIGN(4096);
} }
.bss : .bss :
{ {
bss = .; _bss = .; __bss = .; *(.bss)
*(.bss) . = ALIGN(4096);
. = ALIGN(4096); }
}
end = .; _end = .; __end = .;
end = .; _end = .; __end = .; }
}