Refactoring assembly entry point
This commit is contained in:
parent
dc3803491e
commit
1b207add8c
106
.gitignore
vendored
106
.gitignore
vendored
@ -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
|
18
.travis.yml
18
.travis.yml
@ -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
|
||||||
|
114
Makefile
114
Makefile
@ -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
|
||||||
|
74
README.md
74
README.md
@ -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.
|
||||||
|
22
bochs_cfg
22
bochs_cfg
@ -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
|
108
fs_generator.c
108
fs_generator.c
@ -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;
|
||||||
}
|
}
|
14
grub.cfg
14
grub.cfg
@ -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
|
||||||
}
|
}
|
||||||
|
@ -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 $@
|
@ -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 $@
|
||||||
|
@ -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
19
kernel/cpu/header.asm
Normal 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:
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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
27
kernel/cpu/main.asm
Normal 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
|
@ -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
|
||||||
|
@ -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 $@
|
||||||
|
@ -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;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
}
|
}
|
@ -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
|
||||||
|
@ -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;
|
||||||
}
|
}
|
@ -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
|
||||||
|
@ -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);
|
||||||
}
|
}
|
@ -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
|
||||||
|
@ -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;
|
||||||
}
|
}
|
@ -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
|
||||||
|
@ -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;
|
||||||
}
|
}
|
@ -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
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
@ -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 $@
|
||||||
|
@ -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(;;);
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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));
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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 $@
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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
@ -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--;
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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");
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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 $@
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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!");
|
||||||
}
|
}
|
||||||
|
@ -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
55
link.ld
@ -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 = .;
|
}
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user