├── .gitignore ├── LICENSE ├── bochsrc ├── doc ├── dev.txt └── style.txt ├── grub.cfg ├── libc ├── .gitignore ├── crt0.c ├── ctype │ ├── isalnum.c │ ├── isalpha.c │ ├── isblank.c │ ├── iscntrl.c │ ├── isdigit.c │ ├── isgraph.c │ ├── islower.c │ ├── isprint.c │ ├── ispunct.c │ ├── isspace.c │ ├── isupper.c │ ├── isxdigit.c │ └── makefile ├── dirent │ └── makefile ├── errno │ ├── errno.c │ └── makefile ├── fcntl │ ├── makefile │ └── open.c ├── fnmatch │ └── makefile ├── glob │ └── makefile ├── include │ ├── aio.h │ ├── assert.h │ ├── byteswap.h │ ├── cpio.h │ ├── ctype.h │ ├── dirent.h │ ├── endian.h │ ├── errno.h │ ├── fcntl.h │ ├── fenv.h │ ├── float.h │ ├── fnmatch.h │ ├── glob.h │ ├── inttypes.h │ ├── libgen.h │ ├── limits.h │ ├── locale.h │ ├── math.h │ ├── netdb.h │ ├── paths.h │ ├── poll.h │ ├── setjmp.h │ ├── signal.h │ ├── stdarg.h │ ├── stdbool.h │ ├── stddef.h │ ├── stdint.h │ ├── stdio.h │ ├── stdlib.h │ ├── string.h │ ├── sys │ │ ├── cdefs.h │ │ ├── ctypes.h │ │ ├── dirent.h │ │ ├── ioctl.h │ │ ├── mman.h │ │ ├── param.h │ │ ├── resource.h │ │ ├── stat.h │ │ ├── time.h │ │ ├── times.h │ │ ├── types.h │ │ └── wait.h │ ├── syscall.h │ ├── termios.h │ ├── time.h │ ├── unistd.h │ ├── wchar.h │ └── wctype.h ├── makefile ├── math │ └── makefile ├── signal │ ├── kill.c │ ├── makefile │ ├── raise.c │ ├── sigemptyset.c │ ├── signal.c │ ├── sigprocmask.c │ └── sys_siglist.c ├── stat │ ├── fstat.c │ ├── makefile │ └── stat.c ├── stdio │ ├── fclose.c │ ├── fgetc.c │ ├── fgets.c │ ├── fopen.c │ ├── fprint.c │ ├── fprintf.c │ ├── fputc.c │ ├── fputchar.c │ ├── fputs.c │ ├── fwrite.c │ ├── getc.c │ ├── getchar.c │ ├── gets.c │ ├── makefile │ ├── print.c │ ├── printf.c │ ├── putchar.c │ └── puts.c ├── stdlib │ ├── free.c │ ├── makefile │ ├── malloc.c │ └── strtoll.c ├── string │ ├── makefile │ ├── strcmp.c │ ├── strerror.c │ ├── strlen.c │ ├── strncmp.c │ └── strstr.c ├── syscall.c ├── unistd │ ├── _exit.c │ ├── chdir.c │ ├── close.c │ ├── exec.c │ ├── execve.c │ ├── exit.c │ ├── fork.c │ ├── getcwd.c │ ├── getgid.c │ ├── getpid.c │ ├── lseek.c │ ├── makefile │ ├── read.c │ ├── sync.c │ └── write.c └── wait │ ├── makefile │ ├── wait.c │ └── waitpid.c ├── makefile ├── readme.md ├── src ├── .gitignore ├── ata.c ├── boot.s ├── clock.c ├── common.c ├── cpu.c ├── deepfat.c ├── descriptor_tables.c ├── dev.c ├── dev_null.c ├── dev_stderr.c ├── dev_stdin.c ├── dev_stdout.c ├── elf.c ├── entry_point.c ├── exec.c ├── fat16.c ├── fd.c ├── file.c ├── flat.c ├── fs.c ├── header │ ├── ata.h │ ├── clock.h │ ├── common.h │ ├── cpu.h │ ├── deepfat.h │ ├── descriptor_tables.h │ ├── dev.h │ ├── disasm.h │ ├── elf.h │ ├── exec.h │ ├── fat.h │ ├── fd.h │ ├── file.h │ ├── flat.h │ ├── fs.h │ ├── init.h │ ├── isr.h │ ├── kernel.h │ ├── keyboard.h │ ├── kheap.h │ ├── kstub.h │ ├── kthread.h │ ├── loader.h │ ├── monitor.h │ ├── multiboot.h │ ├── paging.h │ ├── real.h │ ├── sched.h │ ├── signal.h │ ├── single.h │ ├── stdarg.h │ ├── str-util.h │ ├── stream.h │ ├── syscall.h │ ├── tty.h │ ├── userspace.h │ ├── vfs.h │ ├── virtix_page.h │ ├── virtix_proc.h │ ├── vm-error.h │ ├── vm-file.h │ └── vsock.h ├── init.c ├── initramfs │ ├── as_rd.sh │ ├── gen_rd.rb │ ├── hello.x │ └── makefile ├── interrupt.s ├── isr.c ├── keyboard.c ├── kheap.c ├── kthread.c ├── link.ld ├── makefile ├── monitor.c ├── paging.c ├── real.c ├── signal.c ├── single.c ├── str-util.c ├── table.s ├── tty.c ├── userspace.c ├── vfs.c ├── virtix_page.c └── virtix_proc.c └── userland ├── .gitignore ├── link.ld ├── makefile ├── mkdf.sh └── src ├── asserter.c ├── badsh.c ├── error.c ├── escaper.c ├── faulter.c ├── forker.c ├── hello.c ├── mallocer.c ├── reader.c ├── spawner.c ├── typer.c └── waiter.c /.gitignore: -------------------------------------------------------------------------------- 1 | *.iso 2 | *.log 3 | lib/* 4 | *.kdev* 5 | *~ 6 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Austin Bittinger 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /bochsrc: -------------------------------------------------------------------------------- 1 | boot: cdrom 2 | megs: 512 3 | ata1-master: type=cdrom, path=./grub.iso, status=inserted 4 | ata0-master: type=disk, path=userland/hdd.img, status=inserted 5 | -------------------------------------------------------------------------------- /doc/dev.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/16Bitt/virtix/85a3c58f3d3b8932354e85a996a79c377139c201/doc/dev.txt -------------------------------------------------------------------------------- /doc/style.txt: -------------------------------------------------------------------------------- 1 | Style and formatting for code in this project 2 | ---------------------------------- 3 | 4 | 1. All functions and block statements follow the following rule: 5 | TYPE|STMT(ARGS){ 6 | Note that the opening bracket touches the argument. When avoidable, don't use the brackets at all 7 | 8 | 2 . All functions are expected to be defined in a header inside of ../header/ 9 | The only exceptions are functions that are private but need to be defined lower in the file for clarity 10 | 11 | 3. Headers will have the following at the top to avoid collisions: 12 | #define FILE_NAME_H 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /grub.cfg: -------------------------------------------------------------------------------- 1 | set timeout=0 2 | 3 | menuentry "Virtix Debug" { 4 | multiboot /boot/kernel 5 | } 6 | -------------------------------------------------------------------------------- /libc/.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | -------------------------------------------------------------------------------- /libc/crt0.c: -------------------------------------------------------------------------------- 1 | #include "sys/cdefs.h" 2 | #include "syscall.h" 3 | #include "stdio.h" 4 | 5 | extern int main(char** argc, int argv); 6 | extern void _exit(int); 7 | 8 | FILE* stdin = NULL; 9 | FILE* stdout = NULL; 10 | FILE* stderr = NULL; 11 | 12 | void _start(){ 13 | stdin = syscall_0arg(SYS_GETSTDIN); 14 | stdout = syscall_0arg(SYS_GETSTDOUT); 15 | stderr = syscall_0arg(SYS_GETSTDERR); 16 | _exit(main(NULL, NULL)); 17 | } 18 | -------------------------------------------------------------------------------- /libc/ctype/isalnum.c: -------------------------------------------------------------------------------- 1 | #include "ctype.h" 2 | #include "stdbool.h" 3 | 4 | extern bool isnum(char, bool); 5 | 6 | int isalnum(int c){ 7 | return isnum((uchar) c, false); 8 | } 9 | -------------------------------------------------------------------------------- /libc/ctype/isalpha.c: -------------------------------------------------------------------------------- 1 | #include "ctype.h" 2 | 3 | int isalpha(int c){ 4 | return (islower(c) || isupper(c)); 5 | } 6 | -------------------------------------------------------------------------------- /libc/ctype/isblank.c: -------------------------------------------------------------------------------- 1 | #include "ctype.h" 2 | 3 | int isblank(int c){ 4 | return ((c == ' ') || (c == '\t')); 5 | } 6 | -------------------------------------------------------------------------------- /libc/ctype/iscntrl.c: -------------------------------------------------------------------------------- 1 | #include "ctype.h" 2 | 3 | int iscntrl(int c){ 4 | return !isgraph(c) && !isspace(c); 5 | } 6 | -------------------------------------------------------------------------------- /libc/ctype/isdigit.c: -------------------------------------------------------------------------------- 1 | #include "ctype.h" 2 | 3 | int isdigit(int c){ 4 | return C_BETWEEN('0', c, '9'); 5 | } 6 | -------------------------------------------------------------------------------- /libc/ctype/isgraph.c: -------------------------------------------------------------------------------- 1 | #include "ctype.h" 2 | 3 | int isgraph(int c){ 4 | return isprint(c) && !isspace(c); 5 | } 6 | -------------------------------------------------------------------------------- /libc/ctype/islower.c: -------------------------------------------------------------------------------- 1 | #include "ctype.h" 2 | 3 | int islower(int c){ 4 | return C_BETWEEN('a', c, 'z'); 5 | } 6 | -------------------------------------------------------------------------------- /libc/ctype/isprint.c: -------------------------------------------------------------------------------- 1 | #include "ctype.h" 2 | 3 | int isprint(int c){ 4 | return (isprint(c) || isdigit(c) || isalpha(c) || isblank(c) || isspace(c)); 5 | } 6 | -------------------------------------------------------------------------------- /libc/ctype/ispunct.c: -------------------------------------------------------------------------------- 1 | #include "ctype.h" 2 | 3 | int ispunct(int c){ 4 | return (isprint(c) && !isalpha(c) && !isdigit(c)); 5 | } 6 | -------------------------------------------------------------------------------- /libc/ctype/isspace.c: -------------------------------------------------------------------------------- 1 | #include "ctype.h" 2 | 3 | int isspace(int c){ 4 | return ((c == '\t') || (c == '\n') || (c == ' ')); 5 | } 6 | -------------------------------------------------------------------------------- /libc/ctype/isupper.c: -------------------------------------------------------------------------------- 1 | #include "ctype.h" 2 | 3 | int isupper(int c){ 4 | return C_BETWEEN('A', c, 'Z'); 5 | } 6 | -------------------------------------------------------------------------------- /libc/ctype/isxdigit.c: -------------------------------------------------------------------------------- 1 | #include "ctype.h" 2 | 3 | int isxdigit(int c){ 4 | return isdigit(c) || C_BETWEEN('a', c, 'f') || C_BETWEEN('A', c, 'F'); 5 | } 6 | -------------------------------------------------------------------------------- /libc/ctype/makefile: -------------------------------------------------------------------------------- 1 | SOURCES = $(patsubst %.c,%.o,$(wildcard *.c)) 2 | CFLAGS = -fno-builtin -nostdinc -nostdlib -m32 -I../include 3 | CC = i686-elf-gcc 4 | 5 | all: copyup 6 | 7 | clean: 8 | -rm $(SOURCES) 9 | 10 | copyup: $(SOURCES) 11 | -cp $(SOURCES) ../ 12 | 13 | nop: 14 | @@echo Nop 15 | -------------------------------------------------------------------------------- /libc/dirent/makefile: -------------------------------------------------------------------------------- 1 | SOURCES = $(patsubst %.c,%.o,$(wildcard *.c)) 2 | CFLAGS = -fno-builtin -nostdinc -nostdlib -m32 -I../include 3 | CC = i686-elf-gcc 4 | 5 | all: copyup 6 | 7 | clean: 8 | -rm $(SOURCES) 9 | 10 | copyup: $(SOURCES) 11 | -cp $(SOURCES) ../ 12 | 13 | nop: 14 | @@echo Nop 15 | -------------------------------------------------------------------------------- /libc/errno/errno.c: -------------------------------------------------------------------------------- 1 | #include "unistd.h" 2 | 3 | int errno = 0; 4 | -------------------------------------------------------------------------------- /libc/errno/makefile: -------------------------------------------------------------------------------- 1 | SOURCES = $(patsubst %.c,%.o,$(wildcard *.c)) 2 | CFLAGS = -fno-builtin -nostdinc -nostdlib -m32 -I../include 3 | CC = i686-elf-gcc 4 | 5 | all: copyup 6 | 7 | clean: 8 | -rm $(SOURCES) 9 | 10 | copyup: $(SOURCES) 11 | cp $(SOURCES) ../ 12 | 13 | nop: 14 | @@echo Nop 15 | -------------------------------------------------------------------------------- /libc/fcntl/makefile: -------------------------------------------------------------------------------- 1 | SOURCES = $(patsubst %.c,%.o,$(wildcard *.c)) 2 | CFLAGS = -fno-builtin -nostdinc -nostdlib -m32 -I../include 3 | CC = i686-elf-gcc 4 | 5 | all: copyup 6 | 7 | clean: 8 | -rm $(SOURCES) 9 | 10 | copyup: $(SOURCES) 11 | cp $(SOURCES) ../ 12 | 13 | nop: 14 | @@echo Nop 15 | -------------------------------------------------------------------------------- /libc/fcntl/open.c: -------------------------------------------------------------------------------- 1 | #include "fcntl.h" 2 | #include "syscall.h" 3 | #include "stdarg.h" 4 | #include "unistd.h" 5 | #include "sys/stat.h" 6 | #include "errno.h" 7 | 8 | int open(const char* path, int flags, ...){ 9 | struct stat st; 10 | 11 | //Check that the file doesn't exist, if requested 12 | if(flags | O_EXCL){ 13 | int err = stat(path, &st); 14 | if(!err) 15 | return -1; 16 | } 17 | 18 | int fd = syscall_2arg(SYS_OPEN, (uint) path, 0); 19 | 20 | if(fd < 0){ 21 | errno = ENOENT; 22 | return -1; 23 | } 24 | 25 | fstat(fd, &st); 26 | 27 | if(flags | O_APPEND) 28 | lseek(fd, st.st_size, SEEK_SET); 29 | 30 | return fd; 31 | } 32 | -------------------------------------------------------------------------------- /libc/fnmatch/makefile: -------------------------------------------------------------------------------- 1 | SOURCES = $(patsubst %.c,%.o,$(wildcard *.c)) 2 | CFLAGS = -fno-builtin -nostdinc -nostdlib -m32 -I../include 3 | CC = i686-elf-gcc 4 | 5 | all: copyup 6 | 7 | clean: 8 | -rm $(SOURCES) 9 | 10 | copyup: $(SOURCES) 11 | -cp $(SOURCES) ../ 12 | 13 | nop: 14 | @@echo Nop 15 | -------------------------------------------------------------------------------- /libc/glob/makefile: -------------------------------------------------------------------------------- 1 | SOURCES = $(patsubst %.c,%.o,$(wildcard *.c)) 2 | CFLAGS = -fno-builtin -nostdinc -nostdlib -m32 -I../include 3 | CC = i686-elf-gcc 4 | 5 | all: copyup 6 | 7 | clean: 8 | -rm $(SOURCES) 9 | 10 | copyup: $(SOURCES) 11 | -cp $(SOURCES) ../ 12 | 13 | nop: 14 | @@echo Nop 15 | -------------------------------------------------------------------------------- /libc/include/aio.h: -------------------------------------------------------------------------------- 1 | #error "Virtix does not support realtime/asynchronous IO" 2 | -------------------------------------------------------------------------------- /libc/include/assert.h: -------------------------------------------------------------------------------- 1 | #ifndef ASSERT_H 2 | #define ASSERT_H 3 | 4 | #include "sys/cdefs.h" 5 | 6 | __HEADER_START 7 | 8 | #include "stdio.h" 9 | 10 | #define assert(x)\ 11 | if((x) == 0){\ 12 | printf("Assertion failed in %s on line %d: %s\n", __FILE__, __LINE__, __func__);\ 13 | exit(0);\ 14 | } 15 | 16 | __HEADER_END 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /libc/include/byteswap.h: -------------------------------------------------------------------------------- 1 | #ifndef BYTESWAP_H 2 | #define BYTESWAP_H 3 | 4 | #include "sys/cdefs.h" 5 | 6 | __HEADER_START 7 | 8 | #define bswap_16(x) __builtin_bswap16((x)) 9 | #define bswap_32(x) __builtin_bswap32((x)) 10 | #define bswap_64(x) __builtin_bswap64((x)) 11 | 12 | __HEADER_END 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /libc/include/cpio.h: -------------------------------------------------------------------------------- 1 | #error "No CPIO support" 2 | -------------------------------------------------------------------------------- /libc/include/ctype.h: -------------------------------------------------------------------------------- 1 | #ifndef CTYPE_H 2 | #define CTYPE_H 3 | 4 | #include "sys/cdefs.h" 5 | 6 | __HEADER_START 7 | 8 | #define C_BETWEEN(dw, c, up) (((dw) <= c) && (c <= (up))) 9 | 10 | int isalnum(int c); 11 | int iscntrl(int c); 12 | int isspace(int c); 13 | int isalpha(int c); 14 | int isprint(int c); 15 | int isupper(int c); 16 | int islower(int c); 17 | int isgraph(int c); 18 | int ispunct(int c); 19 | int isxdigit(int c); 20 | int isdigit(int c); 21 | int isblank(int c); 22 | 23 | __HEADER_END 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /libc/include/dirent.h: -------------------------------------------------------------------------------- 1 | #ifndef DIRENT_H 2 | #define DIRENT_H 3 | 4 | #include "sys/ctypes.h" 5 | 6 | __HEADER_START 7 | 8 | #include "stdlib.h" 9 | 10 | #ifndef NAME_MAX 11 | #define NAME_MAX 256 12 | #endif 13 | 14 | typedef uint DIR; 15 | 16 | struct dirent{ 17 | ino_t d_ino; 18 | char d_name[NAME_MAX]; 19 | }; 20 | 21 | int closedir(DIR* dir); 22 | int opendir(DIR* dir); 23 | struct dirent* readdir(DIR* dir); 24 | int readdir_r(DIR* dir, struct dirent* entry, struct dirent** list); 25 | void rewinddir(DIR* dir); 26 | void seekdir(DIR* dir, uint to); 27 | uint telldir(DIR* dir); 28 | 29 | __HEADER_END 30 | 31 | #endif 32 | -------------------------------------------------------------------------------- /libc/include/endian.h: -------------------------------------------------------------------------------- 1 | #ifndef ENDIAN_H 2 | #define ENDIAN_H 3 | 4 | #include "sys/cdefs.h" 5 | 6 | __HEADER_START 7 | 8 | 9 | 10 | __HEADER_END 11 | 12 | #endif 13 | -------------------------------------------------------------------------------- /libc/include/errno.h: -------------------------------------------------------------------------------- 1 | #ifndef ERRNO_H 2 | #define ERRNO_H 3 | 4 | #include "sys/cdefs.h" 5 | 6 | __HEADER_START 7 | 8 | extern int errno; 9 | 10 | #define EDOM (-1) 11 | #define ERANGE (-2) 12 | #define EILSEQ (-3) 13 | #define ENOENT (-4) 14 | #define ENOTDIR (-5) 15 | #define EACCES (-6) 16 | #define ENOEXEC (-7) 17 | #define EINTR (-8) 18 | #define EWOULDBLOCK (-9) 19 | #define EAGAIN (-9) 20 | #define EEXIST (-10) 21 | #define EBADF (-11) 22 | 23 | __HEADER_END 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /libc/include/fcntl.h: -------------------------------------------------------------------------------- 1 | #ifndef FCNTL_H 2 | #define FCNTL_H 3 | 4 | #include "sys/cdefs.h" 5 | 6 | __HEADER_START 7 | 8 | #define BUFSIZ 512 9 | 10 | #define F_GETFL 1 11 | #define F_SETFL 2 12 | #define F_SETFD 3 13 | #define F_GETFD 4 14 | #define F_DUPFD 5 15 | 16 | #define FD_CLOEXEC 1 17 | 18 | #define O_NONBLOCK 1 19 | #define O_RDONLY 2 20 | #define O_RDWR 4 21 | #define O_CREAT 8 22 | #define O_TRUNC 16 23 | #define O_WRONLY 32 24 | #define O_EXCL 64 25 | #define O_APPEND 128 26 | 27 | int open(const char* pathname, int flags, ...); 28 | 29 | __HEADER_END 30 | 31 | #endif 32 | -------------------------------------------------------------------------------- /libc/include/fenv.h: -------------------------------------------------------------------------------- 1 | #error "This libc does not support floating point extensions" 2 | -------------------------------------------------------------------------------- /libc/include/float.h: -------------------------------------------------------------------------------- 1 | #error "No floating support in this libc yet" 2 | -------------------------------------------------------------------------------- /libc/include/fnmatch.h: -------------------------------------------------------------------------------- 1 | #ifndef FNMATCH_H 2 | #define FNMATCH_H 3 | 4 | #include "sys/cdefs.h" 5 | 6 | __HEADER_START 7 | 8 | int fnmatch(const char* s1, const char* s2, int flags); 9 | 10 | #define FNM_NOMATCH 1 11 | #define FNM_PATHNAME 2 12 | #define FNM_PERIOD 4 13 | #define FNM_NOESCAPE 8 14 | 15 | __HEADER_END 16 | 17 | #endif 18 | -------------------------------------------------------------------------------- /libc/include/glob.h: -------------------------------------------------------------------------------- 1 | #ifndef GLOB_H 2 | #define GLOB_H 3 | 4 | #include "sys/cdefs.h" 5 | 6 | __HEADER_START 7 | 8 | typedef struct{ 9 | size_t gl_pathc; 10 | char** gl_pathv; 11 | size_t gl_offs; 12 | } glob_t; 13 | 14 | int glob(const char* pattern, int flags, int (*errfunc)(const char* epath, int eerrno), glob_t* pglob); 15 | 16 | //Passed to the flags argument 17 | #define GLOB_APPEND 1 //Start at the end of the current list 18 | #define GLOB_DOOFS 2 //Fill up to the offset with NULL pointers 19 | #define GLOB_ERR 4 //Return on error 20 | #define GLOB_MARK 8 //Directories have slashes 21 | #define GLOB_NOCHECK 16 //If the pattern doesn't match, just return the pattern 22 | #define GLOB_NOESCAPE 32 //Ignore backslash escapes 23 | #define GLOB_NOSORT 64 24 | 25 | //Possible return values 26 | #define GLOB_ABORTED (-1) 27 | #define GLOB_NOMATCH (-2) 28 | #define GLOB_NOSPACE (-3) 29 | #define GLOB_NOSYS (-4) //Reserved according to docs? 30 | 31 | __HEADER_END 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /libc/include/inttypes.h: -------------------------------------------------------------------------------- 1 | #ifndef INTTYPES_H 2 | #define INTTYPES_H 3 | 4 | #include "sys/cdefs.h" 5 | 6 | __HEADER_START 7 | 8 | typedef long int intmax_t; 9 | typedef uint uint32_t; 10 | typedef long unsigned int uintmax_t; 11 | typedef long unsigned int uint64_t; 12 | typedef unsigned short uint16_t; 13 | 14 | __HEADER_END 15 | 16 | #endif 17 | -------------------------------------------------------------------------------- /libc/include/libgen.h: -------------------------------------------------------------------------------- 1 | #ifndef LIBGEN_H 2 | #define LIBGEN_H 3 | 4 | #include "sys/cdefs.h" 5 | 6 | __HEADER_START 7 | 8 | #warning "Unimplemented header file" 9 | 10 | __HEADER_END 11 | 12 | #endif 13 | -------------------------------------------------------------------------------- /libc/include/limits.h: -------------------------------------------------------------------------------- 1 | #ifndef LIMITS_H 2 | #define LIMITS_H 3 | 4 | #include "sys/cdefs.h" 5 | 6 | __HEADER_START 7 | 8 | #define CHAR_BIT 8 9 | #define CHAR_MIN (-127) 10 | #define CHAR_MAX (127) 11 | #define MB_LEN_MAX 1 12 | 13 | //Minimums 14 | #define SCHAR_MIN (-127) 15 | #define SHRT_MIN (-32767) 16 | #define INT_MIN (-2147483647) 17 | #define LONG_MIN (-92233720368544775807) 18 | 19 | //Maximums 20 | #define SCHAR_MAX (-SCHAR_MIN) 21 | #define SHRT_MAX (-SHRT_MIN) 22 | #define INT_MAX (-INT_MIN) 23 | #define LONG_MAX (-LONG_MIN) 24 | 25 | //Unsigned maximums 26 | #define UCHAR_MAX ((SCHAR_MAX * 2) - 1) 27 | #define USHRT_MAX ((SHRT_MAX * 2) - 1) 28 | #define UINT_MAX ((INT_MAX * 2) - 1) 29 | #define ULONG_MAX ((LONG_MAX * 2) - 1) 30 | 31 | #define PATH_MAX 1024 32 | 33 | __HEADER_END 34 | 35 | #endif 36 | -------------------------------------------------------------------------------- /libc/include/locale.h: -------------------------------------------------------------------------------- 1 | #error "No support for locales in this libc (yet)" 2 | -------------------------------------------------------------------------------- /libc/include/math.h: -------------------------------------------------------------------------------- 1 | #ifndef MATH_H 2 | #define MATH_H 3 | 4 | #include "sys/cdefs.h" 5 | 6 | __HEADER_START 7 | 8 | #include "limits.h" 9 | 10 | #define HUGE_VAL MAX_INT 11 | 12 | #error "No floating point operations supported... yet" 13 | 14 | //Wave functions 15 | double sin(double x); 16 | double cos(double x); 17 | double tan(double x); 18 | 19 | //Inverse wave functions 20 | double asin(double x); 21 | double acos(double x); 22 | double atan(double x); 23 | double atan2(double y, double x); 24 | 25 | //Hyperbolic wave functions 26 | double sinh(double x); 27 | double cosh(double x); 28 | double tanh(double x); 29 | 30 | //Logarithms 31 | double log(double x); 32 | double exp(double x); 33 | double log10(double x); 34 | 35 | //Power functions 36 | double pow(double x, double exponent); 37 | double sqrt(double x); 38 | 39 | //Rounding functions 40 | double ceil(double x); 41 | double floor(double x); 42 | 43 | __HEADER_END 44 | 45 | #endif 46 | -------------------------------------------------------------------------------- /libc/include/netdb.h: -------------------------------------------------------------------------------- 1 | #ifndef NETDB_H 2 | #define NETDB_H 3 | 4 | #include "sys/cdefs.h" 5 | 6 | __HEADER_START 7 | 8 | __HEADER_END 9 | 10 | #endif 11 | -------------------------------------------------------------------------------- /libc/include/paths.h: -------------------------------------------------------------------------------- 1 | #ifndef PATHS_H 2 | #define PATHS_H 3 | 4 | #include "sys/cdefs.h" 5 | 6 | __HEADER_START 7 | 8 | 9 | 10 | __HEADER_END 11 | 12 | #endif 13 | -------------------------------------------------------------------------------- /libc/include/poll.h: -------------------------------------------------------------------------------- 1 | #ifndef POLL_H 2 | #define POLL_H 3 | 4 | #include "sys/cdefs.h" 5 | 6 | __HEADER_START 7 | 8 | #warning "Unimplemented header file" 9 | 10 | __HEADER_END 11 | 12 | #endif 13 | -------------------------------------------------------------------------------- /libc/include/setjmp.h: -------------------------------------------------------------------------------- 1 | #ifndef SETJMP_H 2 | #define SETJMP_H 3 | 4 | typedef struct{ 5 | void* ptr[5]; 6 | } jmp_buf_t; 7 | 8 | typedef struct jmp_buf_t* jmp_buf; 9 | 10 | /* 11 | typedef struct{ 12 | void* env[4]; 13 | } jmp_buf; 14 | */ 15 | 16 | #define setjmp(env) __builtin_setjmp((void*) (env)) 17 | #define longjmp(env, value) __builtin_longjmp((void*) (env), (value)) 18 | 19 | #endif 20 | -------------------------------------------------------------------------------- /libc/include/signal.h: -------------------------------------------------------------------------------- 1 | #ifndef SIGNAL_H 2 | #define SIGNAL_H 3 | 4 | #include "sys/cdefs.h" 5 | 6 | __HEADER_START 7 | 8 | #define SIGABRT 0 9 | #define SIGFPE 1 10 | #define SIGILL 2 11 | #define SIGINT 3 12 | #define SIGSEGV 4 13 | #define SIGTERM 5 14 | #define SIGTTIN 6 15 | #define SIGTSTP 7 16 | #define SIGTTOU 8 17 | #define SIGCONT 9 18 | #define SIGPIPE 10 19 | #define SIGQUIT 11 20 | #define SIGHUP 12 21 | #define SIGCHLD 13 22 | 23 | #define NSIG 14 24 | 25 | extern char** sys_siglist; 26 | 27 | #define SIG_IGN (-1) 28 | #define SIG_ERR (-2) 29 | 30 | #define SIG_SETMASK 0 31 | 32 | #define SIG_DFL ((void*) 1) 33 | 34 | int raise(int signal); 35 | int signal(int signal, void (*func)()); 36 | 37 | typedef int sig_atomic_t; 38 | typedef unsigned long int sigset_t; 39 | 40 | int sigemptyset(sigset_t* set); 41 | int sigprocmask(int mask, const sigset_t* set, sigset_t* oset); 42 | int kill(pid_t pid, int signal); 43 | 44 | #ifndef pthread_attr_t 45 | #define pthread_attr_t uint 46 | #endif 47 | 48 | union sigval{ 49 | int sival_int; 50 | void* sival_ptr; 51 | }; 52 | 53 | struct sigevent{ 54 | int sigev_notify; 55 | int sigev_signo; 56 | union sigval sigev_value; 57 | void (*sigev_notify_function)(union sigval); 58 | pthread_attr_t* sigev_notify_attributes; 59 | }; 60 | 61 | struct sigaction{ 62 | void (*sa_handler)(int); 63 | sigset_t sa_mask; 64 | int sa_flags; 65 | void (*sa_sigaction)(int, void*, void*); 66 | }; 67 | 68 | __HEADER_END 69 | 70 | #endif 71 | -------------------------------------------------------------------------------- /libc/include/stdarg.h: -------------------------------------------------------------------------------- 1 | #ifndef STDARG_H 2 | #define STDARG_H 3 | 4 | typedef __builtin_va_list va_list; 5 | #define va_start __builtin_va_start 6 | #define va_end __builtin_va_end 7 | #define va_arg __builtin_va_arg 8 | 9 | #endif 10 | -------------------------------------------------------------------------------- /libc/include/stdbool.h: -------------------------------------------------------------------------------- 1 | #ifndef STDBOOL_H 2 | #define STDBOOL_H 3 | 4 | #include "sys/cdefs.h" 5 | 6 | __HEADER_START 7 | 8 | #define bool _Bool 9 | #define true 1 10 | #define false 0 11 | 12 | #define __bool_true_false_are_defined 1 13 | 14 | __HEADER_END 15 | 16 | #endif 17 | -------------------------------------------------------------------------------- /libc/include/stddef.h: -------------------------------------------------------------------------------- 1 | #ifndef STDDEF_H 2 | #define STDDEF_H 3 | 4 | #include "sys/cdefs.h" 5 | 6 | __HEADER_START 7 | 8 | //In case NULL was defined in another header 9 | #ifndef NULL 10 | #define NULL 0 11 | #endif 12 | 13 | #define offsetof(st, m) __builtin_offsetof((st), (m)) 14 | 15 | typedef int ptrdiff_t; 16 | typedef char wchar_t; 17 | 18 | __HEADER_END 19 | 20 | #endif 21 | -------------------------------------------------------------------------------- /libc/include/stdint.h: -------------------------------------------------------------------------------- 1 | #ifndef STDINT_H 2 | #define STDINT_H 3 | 4 | //Do nothing, these are supplied by GCC for the most part... 5 | 6 | #endif 7 | -------------------------------------------------------------------------------- /libc/include/stdio.h: -------------------------------------------------------------------------------- 1 | #ifndef __STDIO_H 2 | #define __STDIO_H 3 | 4 | #include "sys/cdefs.h" 5 | 6 | __HEADER_START 7 | 8 | #include "fcntl.h" 9 | 10 | typedef unsigned int FILE; 11 | 12 | extern FILE* stdin; 13 | extern FILE* stdout; 14 | extern FILE* stderr; 15 | 16 | #define EOF (-1) 17 | 18 | //General file management 19 | FILE* fopen(const char* name, const char* mode); 20 | int fclose(FILE* f); 21 | 22 | //File output 23 | int fprintf(FILE* f, const char* fmt, ...); 24 | int fprint(FILE* f, char* s); 25 | int fputs(FILE* f, char* str); 26 | int fputchar(FILE* f, char c); 27 | int fputc(FILE* f, char c); 28 | 29 | //Terminal Output 30 | int putchar(char c); 31 | int puts(char* str); 32 | int printf(const char* fmt, ...); 33 | int print(char* s); 34 | 35 | //File input 36 | int fgetc(FILE* f); 37 | int fgetchar(FILE* f); 38 | char* fgets(char* s, int size, FILE* file); 39 | char* gets(char* s); 40 | 41 | __HEADER_END 42 | 43 | #endif 44 | -------------------------------------------------------------------------------- /libc/include/stdlib.h: -------------------------------------------------------------------------------- 1 | #ifndef __STDLIB_H 2 | #define __STDLIB_H 3 | 4 | #include "sys/cdefs.h" 5 | 6 | __HEADER_START 7 | 8 | void* malloc(size_t s); 9 | void free(void* addr); 10 | 11 | long long int strtoll(const char* str, char** endptr, int base); 12 | 13 | __HEADER_END 14 | 15 | #endif 16 | -------------------------------------------------------------------------------- /libc/include/string.h: -------------------------------------------------------------------------------- 1 | #ifndef __STRING_H 2 | #define __STRING_H 3 | 4 | #include "sys/cdefs.h" 5 | 6 | __HEADER_START 7 | 8 | //Memory operations 9 | void* memmove(void* dest, void* src, size_t length); 10 | void* memcpy(void* dest, void* src, size_t length); 11 | int memcmp(void* a, void* b, size_t length); 12 | void* memset(void* ptr, int c, size_t n); 13 | 14 | //String operations 15 | int strcmp(char* str1, char* str2); 16 | int strncmp(char* str1, char* str2, size_t length); 17 | int strcasecmp(char* str1, char* str2); 18 | int strncasecmp(char* str1, char* str2, size_t length); 19 | char* index(char* s, int c); 20 | char* strchr(char* s, int c); 21 | char* rindex(char* s, int c); 22 | char* strrchr(char* s, int c); 23 | char* strcat(char* dest, char* src); 24 | char* strncat(char* dest, char* src, size_t length); 25 | char* strcpy(char* dest, char* src); 26 | char* strdup(char* s); 27 | size_t strlen(char* s); 28 | char* strstr(char* haystack, char* needle); 29 | 30 | char* strerror(int err); 31 | 32 | __HEADER_END 33 | 34 | #endif 35 | -------------------------------------------------------------------------------- /libc/include/sys/cdefs.h: -------------------------------------------------------------------------------- 1 | #ifndef __CDEFS_H 2 | #define __CDEFS_H 3 | 4 | #define __virtix_libc 5 | 6 | #ifdef __cplusplus 7 | #define __HEADER_START extern "C" { 8 | #define __HEADER_END } 9 | #else 10 | #define __HEADER_START 11 | #define __HEADER_END 12 | #endif 13 | 14 | #include "sys/types.h" 15 | 16 | #endif 17 | -------------------------------------------------------------------------------- /libc/include/sys/ctypes.h: -------------------------------------------------------------------------------- 1 | #include "sys/types.h" 2 | -------------------------------------------------------------------------------- /libc/include/sys/dirent.h: -------------------------------------------------------------------------------- 1 | #ifndef __DIRENT_H 2 | #define __DIRENT_H 3 | 4 | #include "sys/cdefs.h" 5 | 6 | __HEADER_START 7 | 8 | #include "dirent.h" 9 | 10 | __HEADER_END 11 | 12 | #endif 13 | -------------------------------------------------------------------------------- /libc/include/sys/ioctl.h: -------------------------------------------------------------------------------- 1 | #ifndef IOCTL_H 2 | #define IOCTL_H 3 | 4 | #include "sys/cdefs.h" 5 | 6 | __HEADER_START 7 | 8 | 9 | 10 | __HEADER_END 11 | 12 | #endif 13 | -------------------------------------------------------------------------------- /libc/include/sys/mman.h: -------------------------------------------------------------------------------- 1 | #ifndef MMAN_H 2 | #define MMAN_H 3 | 4 | #include "sys/cdefs.h" 5 | 6 | __HEADER_START 7 | 8 | #warning "Unimplemented header file" 9 | 10 | __HEADER_END 11 | 12 | #endif 13 | -------------------------------------------------------------------------------- /libc/include/sys/param.h: -------------------------------------------------------------------------------- 1 | #ifndef PARAM_H 2 | #define PARAM_H 3 | 4 | #define VIRTIX_VERSION 0 5 | 6 | #endif 7 | -------------------------------------------------------------------------------- /libc/include/sys/resource.h: -------------------------------------------------------------------------------- 1 | #ifndef RESOURCE_H 2 | #define RESOURCE_H 3 | 4 | #include "sys/cdefs.h" 5 | 6 | __HEADER_START 7 | 8 | #include "sys/time.h" 9 | 10 | typedef uint rlim_t; 11 | 12 | #define PRIO_PROCESS 1 13 | #define PRIO_PGRP 2 14 | #define PRIO_USER 3 15 | 16 | #define RLIM_INFINITY 17 | 18 | #define RUSAGE_SELF 1 19 | #define RUSAGE_CHILDREN 2 20 | 21 | struct rlimit{ 22 | rlim_t rlim_cur; 23 | rlim_t rlim_max; 24 | }; 25 | 26 | struct rusage{ 27 | struct timeval ru_utime; 28 | struct timeval ru_stime; 29 | }; 30 | 31 | __HEADER_END 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /libc/include/sys/stat.h: -------------------------------------------------------------------------------- 1 | #ifndef __STAT_H 2 | #define __STAT_H 3 | 4 | #include "sys/cdefs.h" 5 | 6 | __HEADER_START 7 | 8 | #include "sys/types.h" 9 | 10 | #define S_IFMT 1 11 | #define S_IFDIR 2 12 | #define S_IFREG 4 13 | #define S_ISUID 8 14 | #define S_ISGID 16 15 | #define S_ISVTX 32 16 | #define S_IXUSR 64 17 | #define S_IXOTH 128 18 | #define S_IXGRP 256 19 | 20 | typedef struct stat{ 21 | dev_t st_dev; 22 | ino_t st_ino; 23 | mode_t st_mode; 24 | nlink_t st_nlink; 25 | uid_t st_uid; 26 | gid_t st_gid; 27 | dev_t st_rdev; 28 | off_t st_size; 29 | time_t st_atime; 30 | time_t st_mtime; 31 | time_t st_ctime; 32 | blksize_t st_blksize; 33 | blkcnt_t st_blocks; 34 | } stat_t; 35 | 36 | #define S_ISDIR(m) ((m) & S_IFDIR) 37 | #define S_ISREG(m) ((m) & S_IFREG) 38 | 39 | int stat(const char* path, struct stat* st); 40 | int fstat(int fd, struct stat* st); 41 | 42 | __HEADER_END 43 | 44 | #endif 45 | -------------------------------------------------------------------------------- /libc/include/sys/time.h: -------------------------------------------------------------------------------- 1 | #ifndef TIME_H 2 | #define TIME_H 3 | 4 | #include "sys/cdefs.h" 5 | 6 | __HEADER_START 7 | 8 | typedef uint time_t; 9 | typedef uint suseconds_t; 10 | 11 | struct timeval{ 12 | time_t tv_sec; 13 | suseconds_t tv_usec; 14 | }; 15 | 16 | __HEADER_END 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /libc/include/sys/times.h: -------------------------------------------------------------------------------- 1 | #ifndef TIMES_H 2 | #define TIMES_H 3 | 4 | #include "sys/cdefs.h" 5 | 6 | __HEADER_START 7 | 8 | struct tms{ 9 | clock_t tms_utime; 10 | clock_t tms_stime; 11 | clock_t tms_cutime; 12 | clock_t tms_cstime; 13 | }; 14 | 15 | clock_t times(struct tms* buf); 16 | 17 | __HEADER_END 18 | 19 | #endif 20 | -------------------------------------------------------------------------------- /libc/include/sys/types.h: -------------------------------------------------------------------------------- 1 | #ifndef __TYPE_H 2 | #define __TYPE_H 3 | 4 | typedef unsigned int u32int; 5 | typedef int s32int; 6 | typedef unsigned short u16int; 7 | typedef short s16int; 8 | typedef unsigned char u8int; 9 | typedef char s8int; 10 | typedef int size_t; 11 | typedef unsigned int uint; 12 | typedef unsigned char uchar; 13 | typedef unsigned short ushort; 14 | typedef int ssize_t; 15 | typedef uint clock_t; 16 | 17 | #define NULL 0 18 | #define FALSE 0 19 | #define TRUE (!FALSE) 20 | 21 | #define dev_t uint 22 | #define ino_t uint 23 | #define mode_t uint 24 | #define nlink_t uint 25 | #define uid_t uint 26 | #define gid_t uint 27 | #define off_t uint 28 | #define time_t uint 29 | #define blksize_t uint 30 | #define blkcnt_t uint 31 | #define pid_t uint 32 | 33 | #include "inttypes.h" 34 | 35 | #endif 36 | -------------------------------------------------------------------------------- /libc/include/sys/wait.h: -------------------------------------------------------------------------------- 1 | #ifndef WAIT_H 2 | #define WAIT_H 3 | 4 | #include "sys/cdefs.h" 5 | 6 | __HEADER_START 7 | 8 | pid_t wait(int* status); 9 | pid_t waitpid(pid_t pid, int* status, int flags); 10 | pid_t wait3(int* status, int options, void* unused); //Virtix is a bad bad man 11 | 12 | #define WNOHANG 1 13 | #define WUNTRACED 2 14 | 15 | __HEADER_END 16 | 17 | #endif 18 | -------------------------------------------------------------------------------- /libc/include/syscall.h: -------------------------------------------------------------------------------- 1 | #ifndef __SYSCALL_H 2 | #define __SYSCALL_H 3 | 4 | #include "sys/cdefs.h" 5 | 6 | __HEADER_START 7 | 8 | #define SYS_FORK 0 9 | #define SYS_GETPID 1 10 | #define SYS_GETENV 2 11 | #define SYS_WRITE 3 12 | #define SYS_READ 4 13 | #define SYS_CLOSE 5 14 | #define SYS_EXIT 6 15 | #define SYS_OPEN 7 16 | #define SYS_MALLOC 8 17 | #define SYS_FREE 9 18 | #define SYS_GET_ARGS 10 19 | #define SYS_LSEEK 11 20 | #define SYS_GETSTDIN 12 21 | #define SYS_GETSTDOUT 13 22 | #define SYS_GETSTDERR 14 23 | #define SYS_EXEC 15 24 | #define SYS_SBRK 16 25 | #define SYS_RAISE 17 26 | #define SYS_SIGNAL 18 27 | #define SYS_SIGEXIT 19 28 | #define SYS_WAIT 20 29 | #define SYS_GETGID 21 30 | #define SYS_GETCWD 22 31 | #define SYS_CHDIR 23 32 | #define SYS_EXECVE 24 33 | #define SYS_STAT 25 34 | #define SYS_FSTAT 26 35 | #define SYS_SYNC 27 36 | 37 | int syscall_0arg(uint call_no); 38 | int syscall_1arg(uint call_no, uint arg1); 39 | int syscall_2arg(uint call_no, uint arg1, uint arg2); 40 | int syscall_3arg(uint call_no, uint arg1, uint arg2, uint arg3); 41 | int syscall_4arg(uint call_no, uint arg1, uint arg2, uint arg3, uint arg4); 42 | 43 | __HEADER_END 44 | 45 | #endif 46 | -------------------------------------------------------------------------------- /libc/include/termios.h: -------------------------------------------------------------------------------- 1 | #ifndef TERMIOS_H 2 | #define TERMIOS_H 3 | 4 | #include "sys/cdefs.h" 5 | 6 | __HEADER_START 7 | 8 | typedef uint tcflag_t; 9 | typedef uint speed_t; 10 | typedef uint cc_t; 11 | 12 | __HEADER_END 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /libc/include/time.h: -------------------------------------------------------------------------------- 1 | #error "No time.h support yet" 2 | -------------------------------------------------------------------------------- /libc/include/unistd.h: -------------------------------------------------------------------------------- 1 | #ifndef UNISTD_H 2 | #define UNISTD_H 3 | 4 | #include "sys/cdefs.h" 5 | 6 | __HEADER_START 7 | 8 | #include "sys/stat.h" 9 | #include "sys/dirent.h" 10 | #include "stdio.h" 11 | 12 | #define SEEK_SET 0 13 | #define SEEK_CUR 1 14 | #define SEEK_END 2 15 | 16 | #define _PATH_BSHELL "/bin/sh" 17 | #define _PATH_TTY "/dev/tty" 18 | #define _PATH_DEVNULL "/dev/null" 19 | 20 | #define W_OK 1 21 | #define R_OK 2 22 | #define X_OK 4 23 | 24 | #define PATH_MAX 2048 25 | 26 | int access(const char* path, int flags); 27 | 28 | //File system manipulation 29 | void sync(); 30 | int close(int fd); 31 | int write(int fd, void* addr, size_t length); 32 | int read(int fd, void* addr, size_t length); 33 | int lseek(int fd, int addr, int dir); 34 | 35 | //File execution 36 | int exec(char* path); 37 | int execve(char* path, char** argv, char** env); 38 | void _exit(int retcode); 39 | void exit(int status);int pipe(int fd[2]); 40 | int getgid(); 41 | int getpid(); 42 | int fork(); 43 | 44 | //Directories 45 | int chdir(char* path); 46 | char* getcwd(char* path, size_t size); 47 | 48 | __HEADER_END 49 | 50 | #endif 51 | -------------------------------------------------------------------------------- /libc/include/wchar.h: -------------------------------------------------------------------------------- 1 | #error "No wchar support" 2 | -------------------------------------------------------------------------------- /libc/include/wctype.h: -------------------------------------------------------------------------------- 1 | #error "No wctype.h support" 2 | -------------------------------------------------------------------------------- /libc/makefile: -------------------------------------------------------------------------------- 1 | SOURCES = $(patsubst %.c,%.o,$(wildcard *.c)) 2 | CFLAGS = -fno-builtin -nostdinc -nostdlib -m32 -Iinclude 3 | TARGETS = stdio stat ctype string stdlib errno dirent wait unistd glob fcntl 4 | CC = i686-elf-gcc 5 | AR = i686-elf-ar 6 | INSTALL = /home/socash/cross/lib/gcc/i686-elf/5.0.0/ 7 | 8 | all: $(SOURCES) makesubs 9 | $(AR) rcs libc.a *.o 10 | 11 | clean: cleansubs 12 | -rm $(SOURCES) 13 | -rm *.o *.a 14 | 15 | makesubs: 16 | $(foreach t,$(TARGETS),cd $(t) && make && cd ..;) 17 | 18 | cleansubs: 19 | $(foreach t,$(TARGETS),cd $(t) && make clean && cd ..;) 20 | 21 | install: all 22 | cp libc.a $(INSTALL) 23 | cp -R include/* $(INSTALL)/include/ 24 | 25 | nop: 26 | @@echo Nop 27 | -------------------------------------------------------------------------------- /libc/math/makefile: -------------------------------------------------------------------------------- 1 | SOURCES = $(patsubst %.c,%.o,$(wildcard *.c)) 2 | CFLAGS = -fno-builtin -nostdinc -nostdlib -m32 -I../include 3 | CC = i686-elf-gcc 4 | 5 | all: copyup 6 | 7 | clean: 8 | -rm $(SOURCES) 9 | 10 | copyup: $(SOURCES) 11 | cp $(SOURCES) ../ 12 | 13 | nop: 14 | @@echo Nop 15 | -------------------------------------------------------------------------------- /libc/signal/kill.c: -------------------------------------------------------------------------------- 1 | #include "signal.h" 2 | #include "stdio.h" 3 | 4 | int kill(pid_t pid, int signal){ 5 | puts("WARNING: kill() is a stub"); 6 | return -1; 7 | } 8 | -------------------------------------------------------------------------------- /libc/signal/makefile: -------------------------------------------------------------------------------- 1 | SOURCES = $(patsubst %.c,%.o,$(wildcard *.c)) 2 | CFLAGS = -fno-builtin -nostdinc -nostdlib -m32 -I../include 3 | CC = i686-elf-gcc 4 | 5 | all: copyup 6 | 7 | clean: 8 | -rm $(SOURCES) 9 | 10 | copyup: $(SOURCES) 11 | cp $(SOURCES) ../ 12 | 13 | nop: 14 | @@echo Nop 15 | -------------------------------------------------------------------------------- /libc/signal/raise.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/16Bitt/virtix/85a3c58f3d3b8932354e85a996a79c377139c201/libc/signal/raise.c -------------------------------------------------------------------------------- /libc/signal/sigemptyset.c: -------------------------------------------------------------------------------- 1 | #include "signal.h" 2 | 3 | int sigemptyset(sigset_t* set){ 4 | *set = 0; 5 | } 6 | -------------------------------------------------------------------------------- /libc/signal/signal.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/16Bitt/virtix/85a3c58f3d3b8932354e85a996a79c377139c201/libc/signal/signal.c -------------------------------------------------------------------------------- /libc/signal/sigprocmask.c: -------------------------------------------------------------------------------- 1 | #include "signal.h" 2 | #include "stdio.h" 3 | 4 | int sigprocmask(int mask, const sigset_t* set, sigset_t* oset){ 5 | printf("WARNING: sigprocmask is stubbed\n"); 6 | return -1; 7 | } 8 | -------------------------------------------------------------------------------- /libc/signal/sys_siglist.c: -------------------------------------------------------------------------------- 1 | #include "signal.h" 2 | 3 | char** sys_siglist = { "SIGABRT", "SIGFPE", "SIGILL", "SIGINT", "SIGSEGV", "SIGTERM", "SIGTTIN", "SIGSTP", "SIGTTOU", "SIGCONT", "SIGPIPE", "SIGQUIT", "SIGCHLD" }; 4 | -------------------------------------------------------------------------------- /libc/stat/fstat.c: -------------------------------------------------------------------------------- 1 | #include "sys/stat.h" 2 | #include "syscall.h" 3 | 4 | int fstat(int fd, struct stat* st){ 5 | return syscall_2arg(SYS_FSTAT, fd, (uint) st); 6 | } 7 | -------------------------------------------------------------------------------- /libc/stat/makefile: -------------------------------------------------------------------------------- 1 | SOURCES = $(patsubst %.c,%.o,$(wildcard *.c)) 2 | CFLAGS = -fno-builtin -nostdinc -nostdlib -m32 -I../include 3 | CC = i686-elf-gcc 4 | 5 | all: copyup 6 | 7 | clean: 8 | -rm $(SOURCES) 9 | 10 | copyup: $(SOURCES) 11 | -cp $(SOURCES) ../ 12 | 13 | nop: 14 | @@echo Nop 15 | -------------------------------------------------------------------------------- /libc/stat/stat.c: -------------------------------------------------------------------------------- 1 | #include "sys/stat.h" 2 | #include "syscall.h" 3 | 4 | int stat(const char* path, struct stat* st){ 5 | return syscall_2arg(SYS_STAT, (uint) path, (uint) st); 6 | } 7 | -------------------------------------------------------------------------------- /libc/stdio/fclose.c: -------------------------------------------------------------------------------- 1 | #include "stdio.h" 2 | #include "unistd.h" 3 | 4 | int fclose(FILE* f){ 5 | return close((int) f); 6 | } 7 | -------------------------------------------------------------------------------- /libc/stdio/fgetc.c: -------------------------------------------------------------------------------- 1 | #include "unistd.h" 2 | #include "stdio.h" 3 | 4 | int fgetc(FILE* f){ 5 | char c; 6 | int status = read(f, &c, 1); 7 | 8 | if(status != 0) 9 | return status; 10 | 11 | return c; 12 | } 13 | -------------------------------------------------------------------------------- /libc/stdio/fgets.c: -------------------------------------------------------------------------------- 1 | #include "stdio.h" 2 | #include "unistd.h" 3 | 4 | char* fgets(char* s, int size, FILE* file){ 5 | int i; 6 | for(i = 0; i < size; i++){ 7 | int status = fgetc(file); 8 | if(status < 0) 9 | return NULL; 10 | 11 | s[i] = (unsigned char) status; 12 | 13 | if((unsigned char) status == '\n') 14 | return s; 15 | } 16 | 17 | return s; 18 | } 19 | -------------------------------------------------------------------------------- /libc/stdio/fopen.c: -------------------------------------------------------------------------------- 1 | #include "stdio.h" 2 | #include "unistd.h" 3 | 4 | FILE* fopen(const char* path, const char* mode){ 5 | int flags = 0; 6 | while(*mode != '\0'){ 7 | switch(*mode){ 8 | case 'r': 9 | case 'w': 10 | case '+': 11 | flags |= O_RDWR; 12 | break; 13 | case 'a': 14 | flags |= O_APPEND; 15 | default: 16 | return -1; 17 | } 18 | 19 | mode++; 20 | } 21 | 22 | return (FILE*) open(path, flags); 23 | } 24 | -------------------------------------------------------------------------------- /libc/stdio/fprint.c: -------------------------------------------------------------------------------- 1 | #include "stdio.h" 2 | #include "string.h" 3 | 4 | int fprint(FILE* f, char* s){ 5 | return write(f, s, strlen(s)); 6 | } 7 | -------------------------------------------------------------------------------- /libc/stdio/fprintf.c: -------------------------------------------------------------------------------- 1 | #include "stdio.h" 2 | #include "stdarg.h" 3 | 4 | void print_decimal(FILE* f, int n); 5 | void print_hex(FILE* f, int n); 6 | 7 | int fprintf(FILE* f, const char* fmt, ...){ 8 | va_list params; 9 | va_start(params, fmt); 10 | 11 | int arg = 0; 12 | while(*fmt != '\0'){ 13 | if(*fmt == '%'){ 14 | fmt++; 15 | char op = *fmt; 16 | 17 | switch(op){ 18 | case 'd': 19 | case 'i': 20 | print_decimal(f, va_arg(params, int)); 21 | break; 22 | 23 | case 'x': 24 | case 'X': 25 | print_hex(f, va_arg(params, int)); 26 | break; 27 | 28 | case 'c': 29 | fputchar(f, va_arg(params, int)); 30 | break; 31 | 32 | case 's': 33 | fprint(f, va_arg(params, char*)); 34 | break; 35 | 36 | default: 37 | return -1; 38 | } 39 | } 40 | 41 | else 42 | fputchar(f, *fmt); 43 | 44 | fmt++; 45 | } 46 | 47 | return 0; 48 | } 49 | 50 | void print_decimal(FILE* f, int n){ 51 | if(n == 0){ 52 | fputchar(f, '0'); 53 | return; 54 | } 55 | 56 | if(n < 0){ 57 | fputchar(f, '-'); 58 | n *= -1; 59 | } 60 | 61 | char output[20]; 62 | int end = 0; 63 | while(n != 0){ 64 | char digit = n % 10; 65 | output[end++] = '0' + digit; 66 | n /= 10; 67 | } 68 | 69 | while(end >= 0) 70 | fputchar(f, output[--end]); 71 | } 72 | 73 | void print_hex(FILE* f, int n){ 74 | char* hex_tab = "0123456789ABCDEF"; 75 | char* s = (char*) &n; 76 | int i; 77 | for(i = 4; i >= 0; i--){ 78 | fputchar(f, hex_tab[(s[i] & 0xF0) >> 4]); 79 | fputchar(f, hex_tab[s[i] & 0x0F]); 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /libc/stdio/fputc.c: -------------------------------------------------------------------------------- 1 | #include "stdio.h" 2 | #include "unistd.h" 3 | 4 | int fputc(FILE* file, char c){ 5 | return fputchar(file, c); 6 | } 7 | -------------------------------------------------------------------------------- /libc/stdio/fputchar.c: -------------------------------------------------------------------------------- 1 | #include "stdio.h" 2 | 3 | int fputchar(FILE* f, char c){ 4 | return write(f, &c, 1); 5 | } 6 | -------------------------------------------------------------------------------- /libc/stdio/fputs.c: -------------------------------------------------------------------------------- 1 | #include "stdio.h" 2 | 3 | int fputs(FILE* f, char* str){ 4 | return fprintf(f, "%s\n", str); 5 | } 6 | -------------------------------------------------------------------------------- /libc/stdio/fwrite.c: -------------------------------------------------------------------------------- 1 | #include "stdio.h" 2 | #include "unistd.h" 3 | 4 | size_t fwrite(const void* ptr, size_t size, size_t nmemb, FILE* fd){ 5 | int i; 6 | for(i = 0; i < nmemb; i++){ 7 | write((int) fd, ptr, size); 8 | ptr += size; 9 | } 10 | 11 | return nmemb; 12 | } 13 | -------------------------------------------------------------------------------- /libc/stdio/getc.c: -------------------------------------------------------------------------------- 1 | #include "unistd.h" 2 | #include "stdio.h" 3 | 4 | int getc(FILE* stream){ 5 | char c; 6 | int status = read(stream, &c, 1); 7 | 8 | if(status) 9 | return status; 10 | 11 | return c; 12 | } 13 | -------------------------------------------------------------------------------- /libc/stdio/getchar.c: -------------------------------------------------------------------------------- 1 | #include "unistd.h" 2 | #include "stdio.h" 3 | 4 | int getchar(){ 5 | return getc(stdin); 6 | } 7 | -------------------------------------------------------------------------------- /libc/stdio/gets.c: -------------------------------------------------------------------------------- 1 | #include "unistd.h" 2 | #include "stdio.h" 3 | 4 | //For the love of god, don't ever use this. 5 | char* gets(char* s){ 6 | return fgets(s, 0xFFFFFFFF, stdin); 7 | } 8 | -------------------------------------------------------------------------------- /libc/stdio/makefile: -------------------------------------------------------------------------------- 1 | SOURCES = $(patsubst %.c,%.o,$(wildcard *.c)) 2 | CFLAGS = -fno-builtin -nostdinc -nostdlib -m32 -I../include 3 | CC = i686-elf-gcc 4 | 5 | all: copyup 6 | 7 | clean: 8 | -rm $(SOURCES) 9 | 10 | copyup: $(SOURCES) 11 | cp $(SOURCES) ../ 12 | 13 | nop: 14 | @@echo Nop 15 | -------------------------------------------------------------------------------- /libc/stdio/print.c: -------------------------------------------------------------------------------- 1 | #include "stdio.h" 2 | 3 | int print(char* s){ 4 | return fprint(stdout, s); 5 | } 6 | -------------------------------------------------------------------------------- /libc/stdio/printf.c: -------------------------------------------------------------------------------- 1 | #include "stdio.h" 2 | #include "stdarg.h" 3 | 4 | int printf(const char* fmt, ...){ 5 | va_list params; 6 | va_start(params, fmt); 7 | 8 | while(*fmt != '\0'){ 9 | if(*fmt == '%'){ 10 | fmt++; 11 | char op = *fmt; 12 | switch(op){ 13 | case 'x': 14 | case 'X': 15 | fprintf(stdout, "%x", va_arg(params, int)); 16 | break; 17 | 18 | case 'i': 19 | case 'd': 20 | fprintf(stdout, "%d", va_arg(params, int)); 21 | break; 22 | 23 | case 'c': 24 | putchar(va_arg(params, int)); 25 | break; 26 | 27 | case 's': 28 | print(va_arg(params, char*)); 29 | break; 30 | 31 | default: 32 | return -1; 33 | } 34 | } 35 | 36 | else 37 | putchar(*fmt); 38 | 39 | fmt++; 40 | } 41 | 42 | return; 43 | } 44 | -------------------------------------------------------------------------------- /libc/stdio/putchar.c: -------------------------------------------------------------------------------- 1 | #include "stdio.h" 2 | 3 | int putchar(char c){ 4 | return fputchar(stdout, c); 5 | } 6 | -------------------------------------------------------------------------------- /libc/stdio/puts.c: -------------------------------------------------------------------------------- 1 | #include "stdio.h" 2 | 3 | int puts(char* str){ 4 | return printf("%s\n", str); 5 | } 6 | -------------------------------------------------------------------------------- /libc/stdlib/free.c: -------------------------------------------------------------------------------- 1 | #include "stdlib.h" 2 | #include "syscall.h" 3 | 4 | void free(void* addr){ 5 | (void) syscall_1arg(SYS_FREE, (uint) addr); 6 | return; 7 | } 8 | -------------------------------------------------------------------------------- /libc/stdlib/makefile: -------------------------------------------------------------------------------- 1 | SOURCES = $(patsubst %.c,%.o,$(wildcard *.c)) 2 | CFLAGS = -fno-builtin -nostdinc -nostdlib -m32 -I../include 3 | CC = i686-elf-gcc 4 | 5 | all: copyup 6 | 7 | clean: 8 | -rm $(SOURCES) 9 | 10 | copyup: $(SOURCES) 11 | -cp $(SOURCES) ../ 12 | 13 | nop: 14 | @@echo Nop 15 | -------------------------------------------------------------------------------- /libc/stdlib/malloc.c: -------------------------------------------------------------------------------- 1 | #include "syscall.h" 2 | #include "stdlib.h" 3 | 4 | void* malloc(size_t s){ 5 | return (void*) syscall_1arg(SYS_MALLOC, s); 6 | } 7 | -------------------------------------------------------------------------------- /libc/stdlib/strtoll.c: -------------------------------------------------------------------------------- 1 | #include "stdlib.h" 2 | #include "stdio.h" 3 | #include "string.h" 4 | #include "stdbool.h" 5 | #include "limits.h" 6 | 7 | #define BETWEEN(min, x, max) (((x) >= (min)) && ((x) <= (max))) 8 | 9 | char* get_not_space(char* s){ 10 | int i; 11 | int length = strlen(s); 12 | 13 | for(i = 0; i < length; i++){ 14 | if((s[i] != ' ') || (s[i] != '\t') || (s[i] == '\0')){ 15 | return &s[i]; 16 | } 17 | } 18 | 19 | return &s[length]; 20 | } 21 | 22 | bool isnum(char c, bool no_alpha){ 23 | bool is = false; 24 | 25 | if(BETWEEN('0', c, '9')) 26 | is = true; 27 | 28 | if(!is && !no_alpha && BETWEEN('a', c, 'z')) 29 | is = true; 30 | 31 | if((c == '-') || (c == '+')) 32 | is = true; 33 | 34 | return is; 35 | } 36 | 37 | bool is_delim(char c, bool no_alpha){ 38 | if(!is_num(c, no_alpha)) 39 | return true; 40 | } 41 | 42 | long long int hextoll(char* s){ 43 | long long int ret; 44 | return 0; 45 | } 46 | 47 | long long int dectoll(char* s){ 48 | long long int ret; 49 | 50 | while(is_delim(*s, true)){ 51 | if(*s == '+') //ignore if it's positive 52 | s++; 53 | if(*s == '-') 54 | ret *= -1; 55 | else{ 56 | ret *= 10; 57 | ret += *s - '0'; 58 | } 59 | } 60 | } 61 | 62 | long long int strtoll(const char* str, char** endptr, int base){ 63 | char* s = get_not_space(str); 64 | 65 | switch(base){ 66 | case 0: 67 | if(*(s++) != '0') 68 | return dectoll(s); 69 | 70 | return hextoll(++s); 71 | 72 | case 10: 73 | return dectoll(s); 74 | case 16: 75 | return hextoll(s); 76 | default: 77 | puts("WARNING: unknown base-- returning LONG_LONG_MAX"); 78 | } 79 | 80 | return LONG_MAX * 2; 81 | } 82 | -------------------------------------------------------------------------------- /libc/string/makefile: -------------------------------------------------------------------------------- 1 | SOURCES = $(patsubst %.c,%.o,$(wildcard *.c)) 2 | CFLAGS = -fno-builtin -nostdinc -nostdlib -m32 -I../include 3 | CC = i686-elf-gcc 4 | 5 | all: copyup 6 | 7 | clean: 8 | -rm $(SOURCES) 9 | 10 | copyup: $(SOURCES) 11 | cp $(SOURCES) ../ 12 | 13 | nop: 14 | @@echo Nop 15 | -------------------------------------------------------------------------------- /libc/string/strcmp.c: -------------------------------------------------------------------------------- 1 | #include "string.h" 2 | 3 | int strcmp(char* str1, char* str2){ 4 | size_t len = strlen(str1); 5 | if(len != strlen(str2)) 6 | return 1; 7 | 8 | int i; 9 | for(i = 0; i < len; i++) 10 | if(str1[i] != str2[i]) 11 | return i + 1; 12 | 13 | return 0; 14 | } 15 | -------------------------------------------------------------------------------- /libc/string/strerror.c: -------------------------------------------------------------------------------- 1 | #include "string.h" 2 | 3 | char* strerror(int error){ 4 | return "VIRTIX ERROR"; 5 | } 6 | -------------------------------------------------------------------------------- /libc/string/strlen.c: -------------------------------------------------------------------------------- 1 | #include "string.h" 2 | 3 | size_t strlen(char* s){ 4 | int len = 0; 5 | while(*s != '\0'){ 6 | len++; 7 | s++; 8 | } 9 | 10 | return len; 11 | } 12 | -------------------------------------------------------------------------------- /libc/string/strncmp.c: -------------------------------------------------------------------------------- 1 | #include "string.h" 2 | 3 | int strncmp(char* str1, char* str2, size_t length){ 4 | int i; 5 | for(i = 0; i < length; i++) 6 | if(str1[i] != str2[i]) 7 | return i + 1; 8 | 9 | return 0; 10 | } 11 | -------------------------------------------------------------------------------- /libc/string/strstr.c: -------------------------------------------------------------------------------- 1 | #include "string.h" 2 | 3 | char* strstr(char* haystack, char* needle){ 4 | size_t length = strlen(needle); 5 | size_t haylen = strlen(haystack); 6 | 7 | int i; 8 | for(i = 0; i < haylen - length; i++){ 9 | if(strncmp(&haystack[i], needle, length) == 0) 10 | return &haystack[i]; 11 | } 12 | 13 | return NULL; 14 | } 15 | -------------------------------------------------------------------------------- /libc/syscall.c: -------------------------------------------------------------------------------- 1 | #include "syscall.h" 2 | 3 | int syscall_0arg(uint call_no){ 4 | int ret; 5 | 6 | asm volatile ("movl %0, %%eax" :: "b" (call_no)); 7 | asm volatile ("int $31"); 8 | asm volatile ("movl %%eax, %0" : "=r" (ret)); 9 | return ret; 10 | } 11 | 12 | int syscall_1arg(uint call_no, uint arg1){ 13 | int ret; 14 | asm volatile ("movl %0, %%ebx" :: "c" (arg1)); 15 | asm volatile ("movl %0, %%eax" :: "c" (call_no)); 16 | asm volatile ("int $31"); 17 | asm volatile ("movl %%eax, %0" : "=r" (ret)); 18 | return ret; 19 | } 20 | 21 | int syscall_2arg(uint call_no, uint arg1, uint arg2){ 22 | int ret; 23 | asm volatile ("movl %0, %%ecx" :: "d" (arg2)); 24 | asm volatile ("movl %0, %%ebx" :: "d" (arg1)); 25 | asm volatile ("movl %0, %%eax" :: "d" (call_no)); 26 | asm volatile ("int $31"); 27 | asm volatile ("movl %%eax, %0" : "=r" (ret)); 28 | return ret; 29 | } 30 | 31 | int syscall_3arg(uint call_no, uint arg1, uint arg2, uint arg3){ 32 | int ret; 33 | asm volatile ("movl %0, %%eax" :: "d" (call_no)); 34 | asm volatile ("pushl %eax"); 35 | asm volatile ("movl %0, %%edx" :: "a" (arg3)); 36 | asm volatile ("movl %0, %%ecx" :: "a" (arg2)); 37 | asm volatile ("movl %0, %%ebx" :: "a" (arg1)); 38 | asm volatile ("popl %eax"); 39 | asm volatile ("int $31"); 40 | asm volatile ("movl %%eax, %0" : "=r" (ret)); 41 | return ret; 42 | } 43 | 44 | int syscall_4arg(uint call_no, uint arg1, uint arg2, uint arg3, uint arg4){ 45 | int ret; 46 | asm volatile ("movl %0, %%eax" :: "d" (call_no)); 47 | asm volatile ("pushl %eax"); 48 | asm volatile ("movl %0, %%esi" :: "a" (arg4)); 49 | asm volatile ("movl %0, %%edx" :: "a" (arg3)); 50 | asm volatile ("movl %0, %%ecx" :: "a" (arg2)); 51 | asm volatile ("movl %0, %%ebx" :: "a" (arg1)); 52 | asm volatile ("popl %eax"); 53 | asm volatile ("int $31"); 54 | asm volatile ("movl %%eax, %0" : "=r" (ret)); 55 | return ret; 56 | } 57 | -------------------------------------------------------------------------------- /libc/unistd/_exit.c: -------------------------------------------------------------------------------- 1 | #include "unistd.h" 2 | #include "syscall.h" 3 | 4 | void _exit(int status){ 5 | (void) syscall_1arg(SYS_EXIT, (uint) status); 6 | for(;;); 7 | } 8 | -------------------------------------------------------------------------------- /libc/unistd/chdir.c: -------------------------------------------------------------------------------- 1 | #include "unistd.h" 2 | #include "syscall.h" 3 | 4 | int chdir(char* path){ 5 | return syscall_1arg(SYS_CHDIR, (uint) path); 6 | } 7 | -------------------------------------------------------------------------------- /libc/unistd/close.c: -------------------------------------------------------------------------------- 1 | #include "unistd.h" 2 | #include "syscall.h" 3 | 4 | int close(int f){ 5 | return syscall_1arg(SYS_CLOSE, f); 6 | } 7 | -------------------------------------------------------------------------------- /libc/unistd/exec.c: -------------------------------------------------------------------------------- 1 | #include "unistd.h" 2 | #include "syscall.h" 3 | 4 | int exec(char* file){ 5 | return syscall_1arg(SYS_EXEC, (uint) file); 6 | } 7 | -------------------------------------------------------------------------------- /libc/unistd/execve.c: -------------------------------------------------------------------------------- 1 | #include "unistd.h" 2 | #include "syscall.h" 3 | #include "errno.h" 4 | 5 | int execve(char* path, char** argv, char** env){ 6 | errno = syscall_3arg(SYS_EXECVE, (uint) path, (uint) argv, (uint) env); 7 | 8 | return errno; 9 | } 10 | -------------------------------------------------------------------------------- /libc/unistd/exit.c: -------------------------------------------------------------------------------- 1 | #include "unistd.h" 2 | 3 | void exit(int status){ 4 | _exit(status); 5 | } 6 | -------------------------------------------------------------------------------- /libc/unistd/fork.c: -------------------------------------------------------------------------------- 1 | #include "unistd.h" 2 | #include "syscall.h" 3 | 4 | int fork(){ 5 | return syscall_0arg(SYS_FORK); 6 | } 7 | -------------------------------------------------------------------------------- /libc/unistd/getcwd.c: -------------------------------------------------------------------------------- 1 | #include "sys/param.h" 2 | #include "unistd.h" 3 | #include "syscall.h" 4 | 5 | char* getcwd(char* buf, size_t size){ 6 | return (char*) syscall_1arg(SYS_GETCWD, buf); 7 | } 8 | -------------------------------------------------------------------------------- /libc/unistd/getgid.c: -------------------------------------------------------------------------------- 1 | #include "unistd.h" 2 | #include "syscall.h" 3 | 4 | int getgid(){ 5 | return syscall_0arg(SYS_GETGID); 6 | } 7 | -------------------------------------------------------------------------------- /libc/unistd/getpid.c: -------------------------------------------------------------------------------- 1 | #include "unistd.h" 2 | #include "syscall.h" 3 | 4 | int getpid(){ 5 | return syscall_0arg(SYS_GETPID); 6 | } 7 | -------------------------------------------------------------------------------- /libc/unistd/lseek.c: -------------------------------------------------------------------------------- 1 | #include "unistd.h" 2 | #include "syscall.h" 3 | 4 | int lseek(int file, int direction, int mode){ 5 | return syscall_3arg(SYS_LSEEK, file, direction, mode); 6 | } 7 | -------------------------------------------------------------------------------- /libc/unistd/makefile: -------------------------------------------------------------------------------- 1 | SOURCES = $(patsubst %.c,%.o,$(wildcard *.c)) 2 | CFLAGS = -fno-builtin -nostdinc -nostdlib -m32 -I../include 3 | CC = i686-elf-gcc 4 | 5 | all: copyup 6 | 7 | clean: 8 | -rm $(SOURCES) 9 | 10 | copyup: $(SOURCES) 11 | cp $(SOURCES) ../ 12 | 13 | nop: 14 | @@echo Nop 15 | -------------------------------------------------------------------------------- /libc/unistd/read.c: -------------------------------------------------------------------------------- 1 | #include "unistd.h" 2 | #include "syscall.h" 3 | 4 | int read(int fd, void* buffer, size_t length){ 5 | return syscall_3arg(SYS_READ, (uint) fd, (uint) buffer, (uint) length); 6 | } 7 | -------------------------------------------------------------------------------- /libc/unistd/sync.c: -------------------------------------------------------------------------------- 1 | #include "unistd.h" 2 | #include "syscall.h" 3 | 4 | void sync(){ 5 | (void) syscall_0arg(SYS_SYNC); 6 | } 7 | -------------------------------------------------------------------------------- /libc/unistd/write.c: -------------------------------------------------------------------------------- 1 | #include "unistd.h" 2 | #include "syscall.h" 3 | 4 | int write(int fd, void* buffer, size_t length){ 5 | return syscall_3arg(SYS_WRITE, (uint) fd, (uint) buffer, (uint) length); 6 | } 7 | -------------------------------------------------------------------------------- /libc/wait/makefile: -------------------------------------------------------------------------------- 1 | SOURCES = $(patsubst %.c,%.o,$(wildcard *.c)) 2 | CFLAGS = -fno-builtin -nostdinc -nostdlib -m32 -I../include 3 | CC = i686-elf-gcc 4 | 5 | all: copyup 6 | 7 | clean: 8 | -rm $(SOURCES) 9 | 10 | copyup: $(SOURCES) 11 | -cp $(SOURCES) ../ 12 | 13 | nop: 14 | @@echo Nop 15 | -------------------------------------------------------------------------------- /libc/wait/wait.c: -------------------------------------------------------------------------------- 1 | #include "sys/wait.h" 2 | 3 | pid_t wait(int* status){ 4 | return waitpid(-1, status, 0); 5 | } 6 | -------------------------------------------------------------------------------- /libc/wait/waitpid.c: -------------------------------------------------------------------------------- 1 | #include "sys/wait.h" 2 | #include "syscall.h" 3 | 4 | pid_t waitpid(pid_t pid, int* status, int options){ 5 | int ret; 6 | 7 | while((ret = syscall_3arg(SYS_WAIT, pid, (uint) status, options)) == 0); 8 | //printf("Got %d from SYS_WAIT\n", ret); 9 | 10 | return ret; 11 | } 12 | -------------------------------------------------------------------------------- /makefile: -------------------------------------------------------------------------------- 1 | CC = i686-elf-gcc 2 | LD = i686-elf-ld 3 | 4 | all: 5 | cd src && make 6 | cd libc && make 7 | cd userland && make 8 | cd userland && make disk 9 | 10 | clean: 11 | cd src && make clean 12 | cd libc && make clean 13 | cd userland && make clean 14 | -rm *.iso *.log 15 | 16 | run: dimg 17 | qemu-system-i386 -monitor stdio -net none -vga std -localtime -kernel src/build/kernel -cdrom grub.iso -drive file=userland/hdd.img,if=ide 18 | 19 | debug: all 20 | objcopy --only-keep-debug src/build/kernel src/build/ksym 21 | -qemu-system-i386 -vga std -localtime -kernel src/build/kernel -drive file=userland/hdd.img,if=ide -S -s & sleep 3 22 | (echo target remote 127.0.0.1:1234; cat) | gdb -s src/build/ksym src/build/kernel 23 | -pkill "qemu*" 24 | 25 | dimg: all 26 | mkdir -p src/build/boot 27 | mkdir -p src/build/boot/grub 28 | cp grub.cfg src/build/boot/grub/ 29 | cp src/build/kernel src/build/boot/kernel 30 | -grub-mkrescue -o grub.iso src/build 31 | 32 | bochs: dimg 33 | -echo c | bochs -q 34 | 35 | vbox: dimg 36 | VBoxManage convertfromraw userland/hdd.img userland/hdd.vdi --format vdi 37 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | Virtix - Design is Law 2 | ---------------------- 3 | 4 | Virtix is an operating system with one goal in mind: simplicity. There are plenty of sacrifices, but ultimately, I think that a tiny kernel is incredibly beneficial to the programmer. With something like Linux, I don't even think Torvalds is able to fully comprehend the codebase anymore. Virtix should be able to fit within a programmers mind completely. (I don't want to bash Linux) 5 | 6 | _Design_ 7 | 8 | * Virtix is a monolithic kernel 9 | * The scheduler is a simple cooperative multitasker 10 | * The main file system is a special metafs on top of FAT16, for cross-platform compatibility 11 | * Multiboot compliant 12 | 13 | _Layout_ 14 | 15 | * Kernel code is in `virtix/src/` 16 | * Libc code is in `virtix/libc/` 17 | * Userland files are in `virtix/userland` 18 | * Userland binary sources are in `virtix/userland/src` 19 | * Documentation will eventually be in `virtix/doc` 20 | 21 | _Progress_ 22 | 23 | * Paging 24 | * Multitasking 25 | * A very simple ELF parser 26 | * File streams 27 | * ATA support 28 | * A small libc 29 | * devfs 30 | 31 | _TODO_ 32 | 33 | * Heap implementation needs a lot of work 34 | * ELF loader could definitely be improved 35 | 36 | _Building Requirements_ 37 | 38 | * `nasm` 39 | * GNU coreutils 40 | * `i686-elf-gcc` 41 | * GNU `make` 42 | * `bash` or `zsh` 43 | * `grub2` if you want to make bootable ISO images 44 | * Optionally, `qemu` or `bochs` for testing 45 | 46 | To build simply navigate to `virtix/` and type `make`. If you have `qemu`, and you want to test, type `make run` to build and load into the VM. 47 | 48 | _Special Thanks To_ 49 | 50 | * James Molloy - His guide set up the basis of this kernel 51 | * Github User Levex - His osdev repo had a lot of great examples inside 52 | * Brokenthorn OS development series - Taught me OS dev basics/advanced x86 assembly 53 | * Ralph Brown - His interrupt list is indispencable 54 | * And of course, The OSDev Wiki - This is a spectacular resource 55 | * #osdev on Freenode is a lifesaver 56 | -------------------------------------------------------------------------------- /src/.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | *.log 3 | *.swp 4 | -------------------------------------------------------------------------------- /src/ata.c: -------------------------------------------------------------------------------- 1 | #include "common.h" 2 | #include "monitor.h" 3 | #include "ata.h" 4 | #include "dev.h" 5 | #include "kheap.h" 6 | #include "str-util.h" 7 | #include "clock.h" 8 | 9 | ushort* ata_info; 10 | 11 | ushort disk_channel; 12 | ushort disk_type; 13 | 14 | void select_ata(uchar bus, uint master){ 15 | if(bus == ATA_PRIMARY) 16 | if(master == ATA_MASTER) 17 | outb(ATA_PRIMARY_IO + ATA_REG_HDDEVSEL, ATA_MASTER_SEL); 18 | 19 | else if(master == ATA_SLAVE) 20 | outb(ATA_PRIMARY_IO + ATA_REG_HDDEVSEL, ATA_SLAVE_SEL); 21 | 22 | else 23 | PANIC("requested ATA type is neither master nor slave"); 24 | 25 | else if(bus == ATA_SECONDARY) 26 | if(master == ATA_MASTER) 27 | outb(ATA_SECONDARY_IO + ATA_REG_HDDEVSEL, ATA_MASTER_SEL); 28 | 29 | else if(master == ATA_SLAVE) 30 | outb(ATA_SECONDARY_IO + ATA_REG_HDDEVSEL, ATA_SLAVE_SEL); 31 | 32 | else 33 | PANIC("requested ATA type is neither master nor slave"); 34 | 35 | else 36 | PANIC("bad BUS for ATA"); 37 | } 38 | 39 | uchar ident_ata(uchar bus, uchar drive){ 40 | select_ata(bus, drive); 41 | 42 | ushort io = (bus == ATA_PRIMARY)? ATA_PRIMARY_IO : ATA_SECONDARY_IO; 43 | 44 | outb(io + ATA_REG_SECCOUNT0, 0); 45 | outb(io + ATA_REG_LBA0, 0); 46 | outb(io + ATA_REG_LBA1, 0); 47 | outb(io + ATA_REG_LBA2, 0); 48 | outb(io + ATA_REG_COMMAND, ATA_CMD_IDENTIFY); 49 | 50 | uchar stat = inb(io + ATA_REG_STATUS); 51 | 52 | if(stat){ 53 | while((inb(io + ATA_REG_STATUS) & ATA_SR_BSY) != 0); //Wait until not BSY 54 | 55 | stat = inb(io + ATA_REG_STATUS); 56 | 57 | while(!((stat = inb(io + ATA_REG_STATUS)) & ATA_SR_DRQ)) //Poll until DRQ 58 | if(stat & ATA_SR_ERR){ 59 | ////vga_puts("WARN: ident_ata() found ERR set\n"); 60 | return 0; 61 | } 62 | 63 | int i; 64 | for(i = 0; i < 256; i++) 65 | ata_info[i] = inw(io + ATA_REG_DATA); 66 | 67 | return 1; //Disk is okay 68 | } 69 | 70 | ////vga_puts("WARN: ident_ata() did not read valid drive\n"); 71 | return 0; 72 | } 73 | 74 | void ata_wait(ushort io){ 75 | int i; 76 | for(i = 0; i < 0x4; i++) 77 | inb(io + ATA_REG_ALTSTATUS); 78 | } 79 | 80 | void ata_poll(ushort io){ 81 | ata_wait(io); 82 | uchar stat; 83 | 84 | //vga_puts("ata_poll(): polling\n"); 85 | 86 | do{ 87 | stat = inb(io + ATA_REG_STATUS); 88 | 89 | if(stat & ATA_SR_ERR) 90 | PANIC("ATA driver recieved ERR while polling"); 91 | 92 | } while(!(stat & ATA_SR_DRQ) && (stat & ATA_SR_BSY)); 93 | } 94 | 95 | void ata_read_block(ushort* buffer, uint lba){ 96 | //TODO: these are hardcoded for the primary master 97 | uchar cmd = 0xE0; 98 | ushort io = ATA_PRIMARY_IO; 99 | uchar drive = ATA_MASTER; 100 | 101 | //Preliminary disk setup 102 | outb(io + ATA_REG_HDDEVSEL, (cmd | (uchar) (lba >> 24 & 0x0F))); //Select block 103 | outb(io + ATA_REG_ERROR, 0); //Clear error register 104 | outb(io + ATA_REG_SECCOUNT0, 1); //Read one sector 105 | 106 | outb(io + ATA_REG_LBA0, (uchar) lba & 0xFF); //Lower 8 bits of lba 107 | outb(io + ATA_REG_LBA1, (uchar) ((lba >> 8) & 0xFF)); //Middle 8 bits of lba 108 | outb(io + ATA_REG_LBA2, (uchar) ((lba >> 16) & 0xFF)); //Upper 8 bits of lba 109 | 110 | //Send commands 111 | outb(io + ATA_REG_COMMAND, ATA_CMD_READ_PIO); 112 | ata_poll(io); 113 | 114 | int i; 115 | for(i = 0; i < 256; i++){ 116 | ushort data = inw(io + ATA_REG_DATA); 117 | buffer[i] = data; 118 | } 119 | 120 | ata_wait(io); 121 | } 122 | 123 | void ata_read_blocks(ushort* buffer, uint lba, uint length){ 124 | while(length != 0){ 125 | ata_read_block(buffer, lba); 126 | buffer = (ushort*) ((uint) buffer + 512); 127 | lba++; 128 | length--; 129 | } 130 | } 131 | 132 | void ata_write_block(ushort* buffer, uint lba){ 133 | //TODO: these are hardcoded for the primary master 134 | uchar cmd = 0xE0; 135 | ushort io = ATA_PRIMARY_IO; 136 | uchar drive = ATA_MASTER; 137 | 138 | //Flush the disk cache (necessary for certain hardware setups) 139 | outb(io + ATA_REG_COMMAND, ATA_CMD_CACHE_FLUSH); 140 | ata_wait(io); 141 | outb(io + ATA_REG_COMMAND, ATA_CMD_CACHE_FLUSH_EXT); 142 | ata_poll(io); 143 | 144 | //Preliminary disk setup 145 | outb(io + ATA_REG_HDDEVSEL, (cmd | (uchar) (lba >> 24 & 0x0F))); //Select block 146 | outb(io + ATA_REG_ERROR, 0); //Clear error register 147 | outb(io + ATA_REG_SECCOUNT0, 1); //Read one sector 148 | 149 | outb(io + ATA_REG_LBA0, (uchar) lba & 0xFF); //Lower 8 bits of lba 150 | outb(io + ATA_REG_LBA1, (uchar) ((lba >> 8) & 0xFF)); //Middle 8 bits of lba 151 | outb(io + ATA_REG_LBA2, (uchar) ((lba >> 16) & 0xFF)); //Upper 8 bits of lba 152 | 153 | //Send commands 154 | outb(io + ATA_REG_COMMAND, ATA_CMD_WRITE_PIO); 155 | ata_poll(io); 156 | 157 | int i; 158 | for(i = 0; i < 256; i++) 159 | outw(io + ATA_REG_DATA, buffer[i]); 160 | 161 | ata_wait(io); 162 | } 163 | 164 | void ata_write_blocks(ushort* buffer, uint lba, uint length){ 165 | while(length != 0){ 166 | ata_write_block(buffer, lba); 167 | buffer = (ushort*) ((uint) buffer + 512); 168 | lba++; 169 | length--; 170 | } 171 | } 172 | 173 | void init_ata(){ 174 | ata_info = (ushort*) kmalloc(sizeof(ushort) * 256); //256 word buffer for ident() 175 | 176 | dev_t* dev = (dev_t*) kmalloc(sizeof(dev_t)); 177 | dev->drive = ATA_MASTER; 178 | dev->bus = ATA_PRIMARY; 179 | strmov(dev->name, "hdd"); 180 | 181 | //TODO: don't hardcode root disk 182 | ASSERT(ident_ata(ATA_PRIMARY, ATA_MASTER)); 183 | ASSERT(ident_ata(dev->bus, dev->drive)); 184 | 185 | disk_channel = ATA_PRIMARY; 186 | disk_type = ATA_MASTER; 187 | } 188 | 189 | void ata_read_drv(dev_t* dev, ushort* buffer, uint lba){ 190 | select_ata(dev->bus, dev->drive); 191 | 192 | uchar cmd; 193 | if(dev->drive == ATA_MASTER) 194 | cmd = 0xE0; 195 | else 196 | cmd = 0xF0; 197 | 198 | ushort io; 199 | if(dev->drive == ATA_PRIMARY) 200 | io = ATA_PRIMARY_IO; 201 | else 202 | io = ATA_SECONDARY_IO; 203 | 204 | //Preliminary disk setup 205 | outb(io + ATA_REG_HDDEVSEL, (cmd | (uchar) (lba >> 24 & 0x0F))); //Select block 206 | outb(io + ATA_REG_ERROR, 0); //Clear error register 207 | outb(io + ATA_REG_SECCOUNT0, 1); //Read one sector 208 | 209 | outb(io + ATA_REG_LBA0, (uchar) lba & 0xFF); //Lower 8 bits of lba 210 | outb(io + ATA_REG_LBA1, (uchar) ((lba >> 8) & 0xFF)); //Middle 8 bits of lba 211 | outb(io + ATA_REG_LBA2, (uchar) ((lba >> 16) & 0xFF)); //Upper 8 bits of lba 212 | 213 | //Send commands 214 | outb(io + ATA_REG_COMMAND, ATA_CMD_READ_PIO); 215 | ata_poll(io); 216 | 217 | int i; 218 | for(i = 0; i < 256; i++){ 219 | ushort data = inw(io + ATA_REG_DATA); 220 | buffer[i] = data; 221 | } 222 | 223 | ata_wait(io); 224 | } 225 | 226 | void ata_write_drv(dev_t* dev, ushort* buffer, uint lba){ 227 | select_ata(dev->bus, dev->drive); 228 | 229 | uchar cmd; 230 | if(dev->drive == ATA_MASTER) 231 | cmd = 0xE0; 232 | else 233 | cmd = 0xF0; 234 | 235 | ushort io; 236 | if(dev->drive == ATA_PRIMARY) 237 | io = ATA_PRIMARY_IO; 238 | else 239 | io = ATA_SECONDARY_IO; 240 | 241 | //Flush the disk cache (necessary for certain hardware setups) 242 | outb(io + ATA_REG_COMMAND, ATA_CMD_CACHE_FLUSH); 243 | ata_wait(io); 244 | outb(io + ATA_REG_COMMAND, ATA_CMD_CACHE_FLUSH_EXT); 245 | ata_poll(io); 246 | 247 | //Preliminary disk setup 248 | outb(io + ATA_REG_HDDEVSEL, (cmd | (uchar) (lba >> 24 & 0x0F))); //Select block 249 | outb(io + ATA_REG_ERROR, 0); //Clear error register 250 | outb(io + ATA_REG_SECCOUNT0, 1); //Read one sector 251 | 252 | outb(io + ATA_REG_LBA0, (uchar) lba & 0xFF); //Lower 8 bits of lba 253 | outb(io + ATA_REG_LBA1, (uchar) ((lba >> 8) & 0xFF)); //Middle 8 bits of lba 254 | outb(io + ATA_REG_LBA2, (uchar) ((lba >> 16) & 0xFF)); //Upper 8 bits of lba 255 | 256 | //Send commands 257 | outb(io + ATA_REG_COMMAND, ATA_CMD_WRITE_PIO); 258 | ata_poll(io); 259 | 260 | int i; 261 | for(i = 0; i < 256; i++) 262 | outw(io + ATA_REG_DATA, buffer[i]); 263 | 264 | ata_wait(io); 265 | } 266 | -------------------------------------------------------------------------------- /src/boot.s: -------------------------------------------------------------------------------- 1 | ;This is the mutliboot kernel header 2 | ;Slightly modified version of "Bran's Kernel Development"'s Version 3 | 4 | ;A bunch of magic numbers that multiboot compliant kernels need 5 | MBOOT_PAGE_ALIGN equ 1 6 | MBOOT_MEM_INFO equ 2 7 | MBOOT_HEADER_MAGIC equ 0x1BADB002 8 | MBOOT_HEADER_FLAGS equ MBOOT_PAGE_ALIGN | MBOOT_MEM_INFO 9 | MBOOT_CHECKSUM equ -(MBOOT_HEADER_MAGIC + MBOOT_HEADER_FLAGS) 10 | 11 | [BITS 32] ;32 Bit executable 12 | [GLOBAL mboot] ;Can be called from C 13 | [EXTERN code] ;Use 'code' from outside 14 | [EXTERN bss] ;Use 'bss' from outside 15 | [EXTERN end] ;Use 'end' from outside 16 | 17 | mboot: ;This is simply a data section for the bootloader 18 | dd MBOOT_HEADER_MAGIC 19 | dd MBOOT_HEADER_FLAGS 20 | dd MBOOT_CHECKSUM 21 | 22 | dd mboot 23 | dd code 24 | dd bss 25 | dd end 26 | dd start 27 | 28 | [GLOBAL start] ;Kernel entry point 29 | [EXTERN main] ;Use 'main' from outside 30 | 31 | start: 32 | push esp ;Save initial stack pointer 33 | push ebx ;Save stack frame 34 | cli ;Disable interrupts 35 | call main ;Call C entry point 36 | jmp $ ;Hang when this ends 37 | 38 | [GLOBAL flush_tss] 39 | flush_tss: 40 | mov ax, 0x2B 41 | ltr ax 42 | ret 43 | 44 | [GLOBAL hard_usermode] 45 | [EXTERN hl_cr3] 46 | [EXTERN hl_esp] 47 | [EXTERN hl_eip] 48 | hard_usermode: 49 | mov ax, 0x23 50 | mov ds, ax 51 | mov es, ax 52 | mov fs, ax 53 | mov gs, ax 54 | 55 | mov eax, dword [hl_esp] 56 | push 0x23 57 | push eax 58 | pushf 59 | push 0x1B 60 | push dword [hl_eip] ;Sets up a fake stack 61 | 62 | iret ;Hard load 63 | -------------------------------------------------------------------------------- /src/clock.c: -------------------------------------------------------------------------------- 1 | #include "common.h" 2 | #include "clock.h" 3 | #include "isr.h" 4 | #include "monitor.h" 5 | 6 | uint unix_time = 0; 7 | uint virtix_time = 0; 8 | uint time_div = 0; 9 | uint virtix_mseconds = 0; 10 | 11 | void virtix_clock(registers_t* regs){ 12 | time_div++; 13 | if(time_div == 100){ 14 | time_div = 0; 15 | virtix_time++; 16 | } 17 | } 18 | 19 | void start_timer(unsigned int frequency, clock_handler_t handler){ 20 | register_interrupt_handler(32, handler); 21 | 22 | unsigned int divisor = 1193180 / frequency; 23 | outb(0x43, 0x36); 24 | unsigned char low = (unsigned char) (divisor & 0xFF); 25 | unsigned char high = (unsigned char) ((divisor >> 8) & 0xFF); 26 | outb(0x40, low); 27 | outb(0x40, high); 28 | } 29 | 30 | void init_virtix_clock(){ 31 | start_timer(1, virtix_clock); 32 | init_unix_time(); 33 | } 34 | 35 | uint get_time(){ 36 | return virtix_time + unix_time; 37 | } 38 | 39 | uchar cmos_register(int reg){ 40 | outb(CMOS_CMD, reg); 41 | return inb(CMOS_DATA); 42 | } 43 | 44 | uchar bcd_to_bin(int value){ 45 | return (value & 0xF) + 10 * ((value >> 4) & 0xF); 46 | } 47 | 48 | void init_unix_time(){ 49 | outb(CMOS_CMD, RTC_REG_B); 50 | int flags = inb(CMOS_DATA); 51 | int second, minute, hour, day, month, year; 52 | 53 | second = cmos_register(RTC_SECOND); 54 | minute = cmos_register(RTC_MINUTE); 55 | hour = cmos_register(RTC_HOUR); 56 | day = cmos_register(RTC_DAY); 57 | month = cmos_register(RTC_MONTH); 58 | year = cmos_register(RTC_YEAR); 59 | 60 | if(!(flags & RTC_MODE_BINARY)){ 61 | second = bcd_to_bin(second); 62 | minute = bcd_to_bin(minute); 63 | hour = bcd_to_bin(hour); 64 | day = bcd_to_bin(day); 65 | month = bcd_to_bin(month); 66 | year = bcd_to_bin(year); 67 | } 68 | 69 | if(!(flags & RTC_TIME_24)){ 70 | hour = cmos_register(RTC_HOUR); 71 | if(hour & 0x80) 72 | hour = 12 + bcd_to_bin(hour & 70); 73 | else 74 | hour = bcd_to_bin(hour); 75 | } 76 | 77 | year += 2000; 78 | 79 | vga_fmt("%d:%d:%d %d-%d-%d\n", hour, minute, second, month, day, year); 80 | unix_time = ((year - 1970) * 365 * 24 * 60 * 60)\ 81 | + (30 * month * 24 * 60 * 60)\ 82 | + (24 * day * 60 * 60)\ 83 | + (60 * 60 * hour)\ 84 | + (60 * minute)\ 85 | + second; 86 | 87 | vga_fmt("UNIX time is roughly %ds\n", unix_time); 88 | vga_fmt("Virtix date: %d:%d:%d %d-%d-%d\n", get_hour(), get_minute(), get_seconds(), get_month(), get_day(), get_year() + 1970); 89 | } 90 | 91 | uint get_year(){ 92 | return get_time() / (365 * 24 * 60 * 60); 93 | } 94 | 95 | uint get_month(){ 96 | return (get_time() - (get_year() * 365 * 24 * 60 * 60)) / (30 * 24 * 60 * 60); 97 | } 98 | 99 | uint get_day(){ 100 | return (get_time() - ((get_year() * 365 * 24 * 60 * 60) + (get_month() * 30 * 24 * 60 * 60)))\ 101 | / (24 * 60 * 60); 102 | } 103 | 104 | uint get_hour(){ 105 | return (get_time()\ 106 | - ((get_year() * 365 * 24 * 60 * 60)\ 107 | + (get_month() * 30 * 24 * 60 * 60)\ 108 | + (get_day() * 24 * 60 * 60)))\ 109 | / (60 * 60); 110 | } 111 | 112 | uint get_minute(){ 113 | return (get_time()\ 114 | - ((get_year() * 365 * 24 * 60 * 60)\ 115 | + (get_month() * 30 * 24 * 60 * 60)\ 116 | + (get_day() * 24 * 60 * 60)\ 117 | + (get_hour() * 60 * 60)))\ 118 | / 60; 119 | } 120 | 121 | uint get_seconds(){ 122 | return (get_time()\ 123 | - ((get_year() * 365 * 24 * 60 * 60)\ 124 | + (get_month() * 30 * 24 * 60 * 60)\ 125 | + (get_day() * 24 * 60 * 60)\ 126 | + (get_hour() * 60 * 60)\ 127 | + (get_minute() * 60))); 128 | } 129 | 130 | void sleep(uint seconds){ 131 | uint start = get_seconds(); 132 | while(get_seconds() < (start + seconds)); 133 | } 134 | -------------------------------------------------------------------------------- /src/common.c: -------------------------------------------------------------------------------- 1 | //Port IO, for interfacing non-memory mapped hardware 2 | 3 | #include "common.h" 4 | #include "monitor.h" 5 | #include "isr.h" 6 | 7 | void outb(u16int port, u8int value){ 8 | asm volatile("outb %1, %0"::"dN"(port), "a"(value)); 9 | } 10 | 11 | void outw(ushort port, ushort value){ 12 | asm volatile("outw %1, %0"::"dN"(port), "a"(value)); 13 | } 14 | 15 | u8int inb(u16int port){ 16 | u8int ret; 17 | asm volatile("inb %1, %0":"=a"(ret):"dN"(port)); 18 | return ret; 19 | } 20 | 21 | u16int inw(u16int port){ 22 | u16int ret; 23 | asm volatile("inw %1, %0":"=a"(ret):"dN"(port)); 24 | return ret; 25 | } 26 | 27 | //Basic memory movement routines 28 | void* memset(void* s, int c, size_t n){ 29 | char* str = (char*) s; 30 | 31 | int i; 32 | for(i = 0; i < n; i++) 33 | str[i] = (char) c; 34 | 35 | return s; 36 | } 37 | 38 | void* memcpy(void* dest, const void* src, size_t n){ 39 | char* dest_str = (char*) dest; 40 | char* src_str = (char*) src; 41 | 42 | int i; 43 | for(i = 0; i < n; i++) 44 | dest_str[i] = src_str[i]; 45 | 46 | return dest; 47 | } 48 | 49 | size_t strlen(char* str){ 50 | size_t len = 0; 51 | while(str[len]) 52 | len++; 53 | 54 | return len; 55 | } 56 | 57 | int strcmp(char* str1, char* str2){ 58 | if(strlen(str1) != strlen(str2)) 59 | return -1; 60 | 61 | size_t end = strlen(str1); 62 | int i; 63 | for(i = 0; i < end; i++) 64 | if(str1[i] != str2[i]) 65 | return -1; 66 | 67 | return 0; 68 | } 69 | 70 | void panic(char* msg, char* file, unsigned int line){ 71 | vga_set_fg(RED); 72 | vga_set_bg(WHITE); 73 | 74 | vga_puts("\nPANIC: "); 75 | vga_puts(file); 76 | vga_puts(" on line "); 77 | vga_puts_hex(line); 78 | 79 | vga_puts(" because "); 80 | vga_puts(msg); 81 | 82 | int i; 83 | for(;;) 84 | i++; 85 | } 86 | 87 | void dump_struct(void* structure, size_t bytes){ 88 | char* list = (char*) structure; 89 | 90 | vga_puts_hex((uint) structure); 91 | vga_puts(": "); 92 | 93 | int i; 94 | for(i = 0; i < bytes; i++){ 95 | vga_putc_hex(list[i]); 96 | vga_puts(" "); 97 | } 98 | 99 | vga_puts("\n"); 100 | } 101 | -------------------------------------------------------------------------------- /src/cpu.c: -------------------------------------------------------------------------------- 1 | #include "common.h" 2 | #include "cpu.h" 3 | #include "monitor.h" 4 | #include "virtix_page.h" 5 | 6 | char* cpuid_string = "RiseRiseRise"; 7 | 8 | char* cpu_name(){ 9 | int eax, ebx, ecx, edx; 10 | 11 | asm volatile ("movl $0, %eax"); 12 | asm volatile ("cpuid" : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx)); 13 | 14 | int* strtoint = (int*) cpuid_string; 15 | strtoint[0] = ebx; 16 | strtoint[1] = edx; 17 | strtoint[2] = ecx; 18 | 19 | return cpuid_string; 20 | } 21 | 22 | uint cpu_features(){ 23 | int eax, ebx, ecx, edx; 24 | 25 | asm volatile ("movl $1, %eax"); 26 | asm volatile ("cpuid" : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx)); 27 | return edx; 28 | } 29 | 30 | void cpu_check_fpu(){ 31 | vga_fmt("CPU has features: %X\n", cpu_features()); 32 | ASSERT(cpu_features() & CPU_FEATURE_FPU); 33 | } 34 | -------------------------------------------------------------------------------- /src/deepfat.c: -------------------------------------------------------------------------------- 1 | #include "common.h" 2 | #include "vfs.h" 3 | #include "fat.h" 4 | #include "str-util.h" 5 | #include "deepfat.h" 6 | #include "fd.h" 7 | #include "monitor.h" 8 | #include "dev.h" 9 | #include "kheap.h" 10 | 11 | fs_node_t* df_root; 12 | uint current_inode = 9999; 13 | dev_t* df_dev; 14 | 15 | fs_node_t* mk_empty_node(){ 16 | fs_node_t* node = (fs_node_t*) kmalloc(sizeof(fs_node_t)); 17 | memset(node, 0, sizeof(fs_node_t)); 18 | 19 | node->permissions = 777; 20 | node->uid = node->gid = node->flags = 0; 21 | 22 | node->open = df_open; 23 | node->close = df_close; 24 | 25 | node->dev = df_dev; 26 | node->link = NULL; 27 | 28 | return node; 29 | } 30 | 31 | fs_node_t* mk_empty_fnode(){ 32 | fs_node_t* node = mk_empty_node(); 33 | 34 | node->flags = FS_FILE; 35 | node->read_blk = df_read_blk; 36 | node->write_blk = df_write_blk; 37 | 38 | return node; 39 | } 40 | 41 | fs_node_t* mk_empty_dnode(){ 42 | fs_node_t* node = mk_empty_node(); 43 | 44 | node->flags = FS_DIRECTORY; 45 | node->readdir = df_readdir; 46 | node->finddir = df_finddir; 47 | 48 | return node; 49 | } 50 | 51 | fs_node_t* parse_dir(char* dir){ 52 | fs_node_t* node = mk_empty_dnode(); 53 | fs_node_t* parent = node; 54 | char* fat_buff = (char*) fat_load_full(dir); 55 | 56 | char* str = prep_str(fat_buff); 57 | 58 | ASSERT(strcmp(str, "DEEPFAT") == 0); 59 | str = next_str(str); 60 | ASSERT(strcmp(str, "DEEPDIR") == 0); 61 | str = next_str(str); 62 | 63 | while(strcmp(str, "ENDDIR") != 0){ 64 | char* ent = str; 65 | str = next_str(ent); 66 | fs_node_t* sub; 67 | 68 | /* 69 | vga_puts("\t* creating '"); 70 | vga_puts(str); 71 | vga_puts("'\n"); 72 | */ 73 | 74 | if(strcmp(ent, "DIR") == 0){ 75 | char* name = str; 76 | str = next_str(str); 77 | sub = parse_dir(fat_name_conv(str)); 78 | 79 | strmov(sub->name, name); 80 | strmov(sub->dos_name, str); 81 | fat_dir_t* file = fat_dir_search(fat_name_conv(str)); 82 | sub->inode = file->cluster_low; 83 | sub->length = file->bytes; 84 | sub->flags = FS_DIRECTORY; 85 | 86 | //Callbacks for basic VFS manipulation 87 | sub->open = df_open; 88 | sub->close = df_close; 89 | sub->readdir = readdir_generic; 90 | sub->finddir = df_finddir; 91 | } 92 | 93 | else if(strcmp(ent, "FIL") == 0){ 94 | char* name = str; 95 | str = next_str(str); 96 | sub = mk_empty_fnode(); 97 | 98 | strmov(sub->dos_name, str); 99 | fat_dir_t* file = fat_dir_search(fat_name_conv(str)); 100 | 101 | strmov(sub->name, name); 102 | sub->inode = file->cluster_low; 103 | sub->length = file->bytes; 104 | } 105 | 106 | else{ 107 | PANIC("bad deepFAT directory entry"); 108 | } 109 | 110 | str = ent; 111 | str = next_str(str); 112 | str = next_str(str); 113 | str = next_str(str); 114 | 115 | if(parent->holds == NULL){ 116 | parent->holds = sub; 117 | node = sub; 118 | } 119 | 120 | else{ 121 | node->link = sub; 122 | node = sub; 123 | } 124 | } 125 | 126 | kfree(fat_buff); 127 | return parent; 128 | } 129 | 130 | void init_deepfat(){ 131 | df_dev = (dev_t*) kmalloc(sizeof(dev_t)); 132 | df_dev->read = NULL; 133 | df_dev->write = NULL; 134 | df_dev->block_size = CLUSTER_BSIZE; 135 | df_root = parse_dir(fat_name_conv("DFATROOT.DIR")); 136 | } 137 | 138 | uint df_read_blk(fs_node_t* node, uint offset, uchar* buffer){ 139 | return fat_read_block(node->dos_name, offset, buffer); 140 | } 141 | 142 | uint df_write_blk(fs_node_t* node, uint offset, uchar* buffer){ 143 | uint status = fat_write_block(node->dos_name, offset, buffer); 144 | fat_dir_t* dir = fat_search(node->dos_name); 145 | if(dir != NULL){ 146 | dir->bytes = node->length; 147 | } 148 | return status; 149 | } 150 | 151 | uint df_open(fs_node_t* node, uint index){ 152 | return fd_create(node, index); 153 | } 154 | 155 | void df_close(fs_node_t* node){ 156 | vga_puts("WARN: df_close() is dummy stub\n"); 157 | return; 158 | } 159 | 160 | struct dirent* df_readdir(fs_node_t* node, uint index){ 161 | return NULL; 162 | } 163 | 164 | fs_node_t* df_finddir(fs_node_t* node, char* name){ 165 | return NULL; 166 | } 167 | 168 | char fat_generated[13]; 169 | char* df_mk_name(){ 170 | char* lookup = "0123456789ABCDEF"; 171 | char* extension = "FIL"; 172 | 173 | fat_generated[8] = 0; 174 | 175 | int i, index; 176 | for(i = 28, index = 0; i > -1; i -= 4, index++){ 177 | fat_generated[index] = lookup[(current_inode >> i) & 0xF]; 178 | } 179 | 180 | current_inode++; 181 | 182 | fat_generated[8] = '.'; 183 | 184 | for(i = 0; i < 3; i++) 185 | fat_generated[9 + i] = extension[i]; 186 | 187 | fat_generated[12] = 0; 188 | 189 | return fat_generated; 190 | } 191 | 192 | fat_dir_t* df_new_file(){ 193 | return fat_create(df_mk_name()); 194 | } 195 | 196 | void df_sync(){ 197 | 198 | } 199 | -------------------------------------------------------------------------------- /src/descriptor_tables.c: -------------------------------------------------------------------------------- 1 | #include "common.h" 2 | #include "descriptor_tables.h" 3 | 4 | extern void gdt_flush(u32int); 5 | extern void idt_flush(u32int); 6 | 7 | static void init_gdt(); 8 | static void gdt_set_gate(int index, unsigned int base, unsigned int limit, unsigned char access, unsigned char granularity); 9 | static void init_idt(); 10 | static void idt_set_gate(unsigned char index, unsigned int base, unsigned short sel, unsigned char flags); 11 | 12 | static void write_tss(int, unsigned short, unsigned int); 13 | extern void flush_tss(); 14 | 15 | gdt_entry_t gdt_entries[8]; 16 | gdt_ptr_t gdt_ptr; 17 | idt_entry_t idt_entries[256]; 18 | idt_ptr_t idt_ptr; 19 | 20 | extern unsigned int stack_hold; 21 | 22 | tss_t tss_entry; 23 | 24 | void init_descriptor_tables(){ 25 | init_gdt(); 26 | init_idt(); 27 | } 28 | 29 | static void init_gdt(){ 30 | gdt_ptr.limit = (sizeof(gdt_entry_t) * 7) - 1; 31 | gdt_ptr.base = (unsigned int) &gdt_entries; 32 | 33 | gdt_set_gate(0, 0, 0, 0, 0); 34 | gdt_set_gate(1, 0, 0xFFFFFFFF, 0x9A, 0xCF); 35 | gdt_set_gate(2, 0, 0xFFFFFFFF, 0x92, 0xCF); 36 | gdt_set_gate(3, 0, 0xFFFFFFFF, 0xFA, 0xCF); 37 | gdt_set_gate(4, 0, 0xFFFFFFFF, 0xF2, 0xCF); 38 | write_tss(5, 0x10, stack_hold); 39 | gdt_set_gate(6, 0, 0xFFFFF, 0x92, 0x0); 40 | gdt_set_gate(7, 0, 0xFFFFF, 0x9A, 0x0); 41 | 42 | gdt_flush((unsigned int) &gdt_ptr); 43 | flush_tss(); 44 | } 45 | 46 | static void gdt_set_gate(int index, unsigned int base, unsigned int limit, unsigned char access, unsigned char granularity){ 47 | gdt_entries[index].base_low = (base & 0xFFFF); 48 | gdt_entries[index].base_middle = (base >> 16) & 0xFF; //Base low is actually 24 bits 49 | gdt_entries[index].base_high = (base >> 24) & 0xFF; // 50 | gdt_entries[index].limit_low = (limit & 0xFFFF); 51 | 52 | gdt_entries[index].granularity = (limit >> 16) & 0x0F; 53 | gdt_entries[index].granularity |= granularity & 0xF0; 54 | 55 | gdt_entries[index].access = access; 56 | } 57 | 58 | static void init_idt(){ 59 | idt_ptr.limit = sizeof(idt_entry_t) * 256 - 1; 60 | idt_ptr.base = (unsigned int) &idt_entries; 61 | 62 | memset(&idt_entries, 0, sizeof(idt_entry_t) * 256); 63 | 64 | outb(0x20, 0x11); 65 | outb(0xA0, 0x11); 66 | outb(0x21, 0x20); 67 | outb(0xA1, 0x28); 68 | outb(0x21, 0x04); 69 | outb(0xA1, 0x02); 70 | outb(0x21, 0x01); 71 | outb(0xA1, 0x01); 72 | outb(0x21, 0); 73 | outb(0xA1, 0); 74 | 75 | idt_set_gate(0, (unsigned int) isr0, 0x08, 0x8E); 76 | idt_set_gate(1, (unsigned int) isr1, 0x08, 0x8E); 77 | idt_set_gate(2, (unsigned int) isr2, 0x08, 0x8E); 78 | idt_set_gate(3, (unsigned int) isr3, 0x08, 0x8E); 79 | idt_set_gate(4, (unsigned int) isr4, 0x08, 0x8E); 80 | idt_set_gate(5, (unsigned int) isr5, 0x08, 0x8E); 81 | idt_set_gate(6, (unsigned int) isr6, 0x08, 0x8E); 82 | idt_set_gate(7, (unsigned int) isr7, 0x08, 0x8E); 83 | idt_set_gate(8, (unsigned int) isr8, 0x08, 0x8E); 84 | idt_set_gate(9, (unsigned int) isr9, 0x08, 0x8E); 85 | idt_set_gate(10, (unsigned int) isr10, 0x08, 0x8E); 86 | idt_set_gate(11, (unsigned int) isr11, 0x08, 0x8E); 87 | idt_set_gate(12, (unsigned int) isr12, 0x08, 0x8E); 88 | idt_set_gate(13, (unsigned int) isr13, 0x08, 0x8E); 89 | idt_set_gate(14, (unsigned int) isr14, 0x08, 0x8E); 90 | idt_set_gate(15, (unsigned int) isr15, 0x08, 0x8E); 91 | idt_set_gate(16, (unsigned int) isr16, 0x08, 0x8E); 92 | idt_set_gate(17, (unsigned int) isr17, 0x08, 0x8E); 93 | idt_set_gate(18, (unsigned int) isr18, 0x08, 0x8E); 94 | idt_set_gate(19, (unsigned int) isr19, 0x08, 0x8E); 95 | idt_set_gate(20, (unsigned int) isr20, 0x08, 0x8E); 96 | idt_set_gate(21, (unsigned int) isr21, 0x08, 0x8E); 97 | idt_set_gate(22, (unsigned int) isr22, 0x08, 0x8E); 98 | idt_set_gate(23, (unsigned int) isr23, 0x08, 0x8E); 99 | idt_set_gate(24, (unsigned int) isr24, 0x08, 0x8E); 100 | idt_set_gate(25, (unsigned int) isr25, 0x08, 0x8E); 101 | idt_set_gate(26, (unsigned int) isr26, 0x08, 0x8E); 102 | idt_set_gate(27, (unsigned int) isr27, 0x08, 0x8E); 103 | idt_set_gate(28, (unsigned int) isr28, 0x08, 0x8E); 104 | idt_set_gate(29, (unsigned int) isr29, 0x08, 0x8E); 105 | idt_set_gate(30, (unsigned int) isr30, 0x08, 0x8E); 106 | idt_set_gate(31, (unsigned int) isr31, 0x08, 0x8E); 107 | idt_set_gate(0x80, (unsigned int) isr0x80, 0x08, 0x8E); 108 | idt_set_gate(32, (unsigned int) irq0, 0x08, 0x8E); 109 | idt_set_gate(33, (unsigned int) irq1, 0x08, 0x8E); 110 | idt_set_gate(34, (unsigned int) irq2, 0x08, 0x8E); 111 | idt_set_gate(35, (unsigned int) irq3, 0x08, 0x8E); 112 | idt_set_gate(36, (unsigned int) irq4, 0x08, 0x8E); 113 | idt_set_gate(37, (unsigned int) irq5, 0x08, 0x8E); 114 | idt_set_gate(38, (unsigned int) irq6, 0x08, 0x8E); 115 | idt_set_gate(39, (unsigned int) irq7, 0x08, 0x8E); 116 | idt_set_gate(40, (unsigned int) irq8, 0x08, 0x8E); 117 | idt_set_gate(41, (unsigned int) irq9, 0x08, 0x8E); 118 | idt_set_gate(42, (unsigned int) irq10, 0x08, 0x8E); 119 | idt_set_gate(43, (unsigned int) irq11, 0x08, 0x8E); 120 | idt_set_gate(44, (unsigned int) irq12, 0x08, 0x8E); 121 | idt_set_gate(45, (unsigned int) irq13, 0x08, 0x8E); 122 | idt_set_gate(46, (unsigned int) irq14, 0x08, 0x8E); 123 | idt_set_gate(47, (unsigned int) irq15, 0x08, 0x8E); 124 | 125 | idt_flush((u32int) &idt_ptr); 126 | } 127 | 128 | static void idt_set_gate(unsigned char index, unsigned int base, unsigned short sel, unsigned char flags){ 129 | idt_entries[index].base_lo = base & 0xFFFF; 130 | idt_entries[index].base_hi = (base >> 16) & 0xFFFF; 131 | idt_entries[index].sel = sel; 132 | idt_entries[index].always0 = 0; 133 | idt_entries[index].flags = flags | 0x60; 134 | } 135 | 136 | static void write_tss(int num, unsigned short ss0, unsigned int esp0){ 137 | unsigned int base = (unsigned int) &tss_entry; 138 | unsigned int limit = base + sizeof(tss_entry); 139 | 140 | gdt_set_gate(num, base, limit, 0xE9, 0x00); 141 | memset(&tss_entry, 0, sizeof(tss_entry)); 142 | 143 | tss_entry.ss0 = ss0; 144 | tss_entry.esp0 = esp0; 145 | tss_entry.cs = 0x0B; 146 | tss_entry.ss = tss_entry.ds = tss_entry.es = tss_entry.fs = tss_entry.gs = 0x13; 147 | } 148 | 149 | void set_kernel_stack(unsigned int stack){ 150 | tss_entry.esp0 = stack; 151 | } 152 | -------------------------------------------------------------------------------- /src/dev.c: -------------------------------------------------------------------------------- 1 | #include "common.h" 2 | #include "monitor.h" 3 | #include "vfs.h" 4 | #include "dev.h" 5 | #include "deepfat.h" 6 | #include "kheap.h" 7 | #include "str-util.h" 8 | 9 | void mkdev(char* name, read_block_t read, write_block_t write){ 10 | if(fs_path(df_root, "/dev") == NULL){ 11 | WARN("Can't make device, no path for /dev") 12 | return; 13 | } 14 | 15 | NOTIFY(name) 16 | 17 | char* path = (char*) kmalloc(strlen(name) + strlen("/dev/") + 2); 18 | strmov(path, "/dev/"); 19 | strmov(&path[strlen("/dev/")], name); 20 | 21 | fs_node_t* node = vfs_touch(df_root, path); 22 | 23 | if(node == NULL){ 24 | WARN("couldn't resolve path") 25 | return; 26 | } 27 | 28 | node->read_blk = read; 29 | node->write_blk = write; 30 | 31 | node->dev = (dev_t*) kmalloc(sizeof(dev_t)); 32 | node->dev->read = read; 33 | node->dev->write = write; 34 | node->dev->block_size = 512; 35 | } 36 | 37 | uint dev_read(fs_node_t* dev, uint offset, char* buffer){ 38 | if(dev->read_blk == NULL){ 39 | WARN("can't read from device"); 40 | return (uint) -1; 41 | } 42 | 43 | return dev->read_blk(dev, offset, buffer); 44 | } 45 | 46 | 47 | uint dev_write(fs_node_t* dev, uint offset, char* buffer){ 48 | if(dev->write_blk == NULL){ 49 | WARN("can't write to device"); 50 | return (uint) -1; 51 | } 52 | 53 | return dev->write_blk(dev, offset, buffer); 54 | } 55 | -------------------------------------------------------------------------------- /src/dev_null.c: -------------------------------------------------------------------------------- 1 | #include "common.h" 2 | #include "dev.h" 3 | #include "vfs.h" 4 | 5 | uint dev_null_read(struct fs_node* node, uint offset, uchar* buffer){ 6 | int i; 7 | for(i = 0; i < 512; i++){ 8 | buffer[i] = 0; 9 | } 10 | 11 | return 0; 12 | } 13 | 14 | void dev_null(){ 15 | mkdev("null", dev_null_read, NULL); 16 | } 17 | -------------------------------------------------------------------------------- /src/dev_stderr.c: -------------------------------------------------------------------------------- 1 | #include "dev.h" 2 | #include "monitor.h" 3 | #include "vfs.h" 4 | #include "deepfat.h" 5 | #include "tty.h" 6 | 7 | extern uchar vga_color; 8 | 9 | uint dev_stderr_write(fs_node_t* node, uint offset, uchar* buffer){ 10 | tty_putc(*buffer); 11 | return 0; 12 | } 13 | 14 | void dev_stderr(){ 15 | mkdev("stderr", NULL, dev_stderr_write); 16 | fs_node_t* node = fs_path(df_root, "/dev/stderr"); 17 | node->dev->block_size = 0; 18 | } 19 | -------------------------------------------------------------------------------- /src/dev_stdin.c: -------------------------------------------------------------------------------- 1 | #include "common.h" 2 | #include "dev.h" 3 | #include "vfs.h" 4 | #include "monitor.h" 5 | #include "deepfat.h" 6 | #include "isr.h" 7 | #include "keyboard.h" 8 | 9 | extern uchar keyboard_getc(); 10 | 11 | uint dev_stdin_read(fs_node_t* node, uint offset, uchar* buffer){ 12 | sti(); //Reenable-- this is a safe place to allow interrupts in ring 0 13 | 14 | wait_for_update: 15 | *buffer = keyboard_getc(); 16 | 17 | if(*buffer == 0){ 18 | hlt(); 19 | goto wait_for_update; 20 | } 21 | 22 | cli(); //Disable them again just in case 23 | return 0; 24 | } 25 | 26 | void dev_stdin(){ 27 | mkdev("stdin", dev_stdin_read, NULL); 28 | fs_node_t* node = fs_path(df_root, "/dev/stdin"); 29 | node->dev->block_size = 0; 30 | node->length = 0xFFFFFFFF; 31 | } 32 | -------------------------------------------------------------------------------- /src/dev_stdout.c: -------------------------------------------------------------------------------- 1 | #include "common.h" 2 | #include "dev.h" 3 | #include "vfs.h" 4 | #include "deepfat.h" 5 | #include "monitor.h" 6 | #include "tty.h" 7 | 8 | uint stdout_write(fs_node_t* node, uint offset, uchar* buffer){ 9 | tty_putc(*buffer); 10 | 11 | return 0; 12 | } 13 | 14 | void dev_stdout(){ 15 | mkdev("stdout", NULL, stdout_write); 16 | fs_node_t* node = fs_path(df_root, "/dev/stdout"); 17 | node->dev->block_size = 0; 18 | } 19 | -------------------------------------------------------------------------------- /src/elf.c: -------------------------------------------------------------------------------- 1 | #include "common.h" 2 | #include "elf.h" 3 | #include "monitor.h" 4 | #include "virtix_proc.h" 5 | #include "kheap.h" 6 | #include "virtix_page.h" 7 | 8 | unsigned char validate_elf_data[] = { ELFMAG0, ELFMAG1, ELFMAG2, ELFMAG3 }; 9 | 10 | int validate_elf(void* data){ 11 | elf32_ehdr* header = (elf32_ehdr*) data; 12 | 13 | int i; 14 | for(i = 0; i < 4; i++) 15 | if(header->e_ident[i] != validate_elf_data[i]) 16 | return 0; 17 | 18 | return 1; 19 | } 20 | 21 | virtix_proc_t* elf_load(void* elf_data){ 22 | if(validate_elf(elf_data) == 0){ 23 | vga_puts("elf_load(): validation failed\n"); 24 | return (virtix_proc_t*) NULL; 25 | } 26 | 27 | elf32_ehdr* header = (elf32_ehdr*) elf_data; 28 | 29 | if(header->e_type != 2){ 30 | vga_puts("elf_load(): wrong executable type\n"); 31 | return (virtix_proc_t*) NULL; 32 | } 33 | 34 | virtix_proc_t* proc = mk_empty_proc(); 35 | proc->name = "ELF_PROGRAM"; 36 | proc->registers.eip = header->e_entry; 37 | 38 | switch_vpage_dir(proc->cr3); 39 | uint stk = (uint) kmalloc_a(PAGE_S); 40 | proc->registers.useresp = 0x40000000 - (PAGE_S / 2); 41 | proc->registers.ebp = proc->registers.useresp; 42 | proc->registers.esp = proc->registers.useresp; 43 | vpage_map_user(proc->cr3, stk, 0x40000000 - PAGE_S); 44 | 45 | elf32_phdr* phdr = (elf32_phdr*) (((unsigned int) elf_data) + header->e_phoff); 46 | 47 | int i; 48 | for(i = 0; i < header->e_phnum; i++, phdr++){ 49 | switch(phdr->p_type){ 50 | case 0: 51 | break; 52 | case 1: 53 | i += 0; 54 | //NOTIFY("Allocating space for ELF binary section...") 55 | unsigned int loc = (unsigned int) kmalloc_a(PAGE_S); 56 | vpage_map_user(proc->cr3, loc, phdr->p_vaddr); 57 | memcpy((void*) phdr->p_vaddr, ((void*) ((unsigned int) elf_data) + phdr->p_offset), phdr->p_filesz); 58 | if(phdr->p_filesz > PAGE_S) 59 | PANIC("ELF binary section too large"); 60 | break; 61 | default: 62 | /*vga_set_fg(RED); 63 | vga_puts("type="); 64 | vga_puts_hex(phdr->p_type); 65 | vga_puts("\n");*/ 66 | WARN("unknown header type"); 67 | } 68 | } 69 | 70 | switch_vpage_dir(root_vpage_dir); 71 | return proc; 72 | } 73 | -------------------------------------------------------------------------------- /src/entry_point.c: -------------------------------------------------------------------------------- 1 | //Kernel specific 2 | #include "common.h" 3 | #include "monitor.h" 4 | #include "descriptor_tables.h" 5 | #include "isr.h" 6 | #include "multiboot.h" 7 | #include "fs.h" 8 | #include "kheap.h" 9 | #include "virtix_page.h" 10 | 11 | //Untested 12 | #include "virtix_proc.h" 13 | #include "elf.h" 14 | #include "fat.h" 15 | #include "ata.h" 16 | #include "deepfat.h" 17 | #include "file.h" 18 | #include "init.h" 19 | #include "keyboard.h" 20 | #include "real.h" 21 | #include "userspace.h" 22 | #include "fd.h" 23 | #include "exec.h" 24 | #include "cpu.h" 25 | #include "tty.h" 26 | 27 | void* stack = NULL; 28 | 29 | unsigned int stack_hold; 30 | 31 | int main(struct multiboot* mboot_ptr, unsigned int esp){ 32 | stack_hold = esp; 33 | vga_reset(); 34 | vga_clear(); 35 | 36 | NOTIFY("loaded Kernel") 37 | init_descriptor_tables(); 38 | NOTIFY("initialized memory protection map") 39 | 40 | NOTIFY("making kheap") 41 | init_kheap(); 42 | 43 | NOTIFY("attempting to initialize paging") 44 | virtix_page_init(); 45 | 46 | /* 47 | vga_puts("main(): relocating modules\n"); 48 | void* mod_loc = kmalloc_a(1024 * 10); 49 | memcpy(mod_loc, (void*) mboot_ptr->mods_addr, 1024 * 6); 50 | 51 | vga_puts("main(): initializing read-only ramdisk\n"); 52 | mnt_initrd((unsigned int) mod_loc); 53 | */ 54 | 55 | NOTIFY("registering default handlers") 56 | register_default_handlers(); 57 | 58 | NOTIFY("registering userspace handler") 59 | init_userspace(); 60 | 61 | NOTIFY("starting interrupts") 62 | sti(); 63 | 64 | NOTIFY("starting clock"); 65 | init_virtix_clock(); 66 | 67 | /* 68 | vga_puts("main(): loading a binary...\n"); 69 | virtix_proc_t* proc = elf_load(get_file_data("hello.x")); 70 | 71 | vga_puts("main(): entering usermode\n"); 72 | enter_userspace(proc); 73 | */ 74 | 75 | NOTIFY("starting ATA driver") 76 | init_ata(); 77 | 78 | NOTIFY("starting FAT driver") 79 | init_fat(); 80 | 81 | NOTIFY("starting deepFAT driver") 82 | init_deepfat(); 83 | 84 | NOTIFY("starting file descriptor interface") 85 | init_fd(); 86 | 87 | NOTIFY("making /dev") 88 | vfs_mkdir(df_root, "/dev"); 89 | 90 | NOTIFY("starting VFS drivers"); 91 | driver_init(); 92 | 93 | NOTIFY("enabling keyboard"); 94 | init_keyboard(); 95 | 96 | NOTIFY("getting CPUID string"); 97 | NOTIFY(cpu_name()); 98 | 99 | NOTIFY("checking for an FPU"); 100 | cpu_check_fpu(); 101 | 102 | FILE f = kfopen("/dev/stdout", 0); 103 | char* msg = "Test write to /dev/stdout\n"; 104 | kfwrite(f, strlen(msg), msg); 105 | kfclose(f); 106 | msg = "Test write to /dev/stderr\n"; 107 | f = kfopen("/dev/stderr", 0); 108 | kfwrite(f, strlen(msg), msg); 109 | kfclose(f); 110 | 111 | fat_create("test.txt"); 112 | fat_write_block("test.txt", 0, "This is a test write to see if FAT is garbage."); 113 | fat_sync(); 114 | 115 | kexec("/bin/badsh"); 116 | 117 | NOTIFY("syncing FAT") 118 | fat_sync(); 119 | 120 | WARN("reached end of execution, hanging the CPU") 121 | cli(); 122 | hlt(); 123 | } 124 | -------------------------------------------------------------------------------- /src/exec.c: -------------------------------------------------------------------------------- 1 | #include "common.h" 2 | #include "file.h" 3 | #include "exec.h" 4 | #include "virtix_proc.h" 5 | #include "elf.h" 6 | #include "monitor.h" 7 | #include "kheap.h" 8 | 9 | uint kexec(char* path){ 10 | FILE f = kfopen(path, 0); 11 | if(f == (FILE) -1) 12 | return (uint) -1; 13 | 14 | struct stat* st = (struct stat*) kmalloc(sizeof(struct stat)); 15 | kfstat(f, st); 16 | size_t size = st->st_size; 17 | kfree(st); 18 | char* buffer = (char*) kmalloc(size); 19 | kfread(f, size, buffer); 20 | virtix_proc_t* proc = elf_load((void*) buffer); 21 | kfree(buffer); 22 | if(proc == NULL) 23 | return (uint) -1; 24 | 25 | proc->stdin = kfopen("/dev/stdin", 0); 26 | proc->stdout = kfopen("/dev/stdout", 0); 27 | proc->stderr = kfopen("/dev/stderr", 0); 28 | 29 | NOTIFY(path); 30 | init_procs(proc); 31 | } 32 | 33 | uint kexec_pipes(char* path, char* stdin, char* stdout, char* stderr){ 34 | FILE f = kfopen(path, 0); 35 | if(f == (FILE) -1) 36 | return (uint) -1; 37 | 38 | struct stat* st = (struct stat*) kmalloc(sizeof(struct stat)); 39 | kfstat(f, st); 40 | size_t size = st->st_size; 41 | kfree(st); 42 | char* buffer = (char*) kmalloc(size); 43 | kfread(f, size, buffer); 44 | virtix_proc_t* proc = elf_load((void*) buffer); 45 | kfree(buffer); 46 | if(proc == NULL) 47 | return (uint) -1; 48 | 49 | proc->stdin = kfopen("/dev/stdin", 0); 50 | proc->stdout = kfopen("/dev/stderr", 0); 51 | proc->stderr = kfopen("/dev/stderr", 0); 52 | 53 | init_procs(proc); 54 | } 55 | 56 | uint uexec(char* path){ 57 | //NOTIFY("trapped exec() call") 58 | susp_proc(current_proc->pid); 59 | 60 | FILE f = kfopen(path, 0); 61 | if(f == (uint) -1){ 62 | wake_proc(current_proc->pid); 63 | return (uint) -1; 64 | } 65 | 66 | struct stat* st = (struct stat*) kmalloc(sizeof(struct stat)); 67 | kfstat(f, st); 68 | size_t size = st->st_size; 69 | kfree(st); 70 | char* buffer = (char*) kmalloc(size); 71 | kfread(f, size, buffer); 72 | virtix_proc_t* proc = elf_load((void*) buffer); 73 | kfree(buffer); 74 | if(proc == NULL) 75 | return (uint) -1; 76 | 77 | proc->stdin = kfopen("/dev/stdin", 0); 78 | proc->stdout = kfopen("/dev/stdout", 0); 79 | proc->stderr = kfopen("/dev/stderr", 0); 80 | proc->parent = current_proc; 81 | proc->gid = current_proc->pid; 82 | 83 | spawn_proc(proc); 84 | return 0; 85 | } 86 | -------------------------------------------------------------------------------- /src/fd.c: -------------------------------------------------------------------------------- 1 | #include "common.h" 2 | #include "monitor.h" 3 | #include "vfs.h" 4 | #include "fd.h" 5 | #include "deepfat.h" 6 | #include "kheap.h" 7 | #include "str-util.h" 8 | #include "fat.h" 9 | 10 | fd_t fd_list[MAX_FD]; 11 | 12 | void init_fd(){ 13 | memset(fd_list, 0, sizeof(fd_t) * MAX_FD); 14 | } 15 | 16 | fs_node_t* fd_lookup(uint fd){ 17 | if(fd >= MAX_FD) 18 | return NULL; 19 | 20 | return fd_list[fd].node; 21 | } 22 | 23 | uint calc_blk_offset(uint bs, uint offs){ 24 | uint index = 0; 25 | 26 | if(bs == 1) 27 | return offs; 28 | 29 | while(bs < offs){ 30 | index++; 31 | offs--; 32 | } 33 | 34 | return index; 35 | } 36 | 37 | uint calc_buf_offset(uint bs, uint offs){ 38 | return bs * calc_blk_offset(bs, offs) - offs; 39 | } 40 | 41 | uint fd_create(fs_node_t* node, uint offset){ 42 | int i; 43 | 44 | for(i = 0; i < MAX_FD; i++){ 45 | if(fd_list[i].present == 0){ 46 | fd_list[i].node = node; 47 | strmov(fd_list[i].name, node->name); 48 | fd_list[i].block_size = node->dev->block_size; 49 | fd_list[i].buffer = (char*) kmalloc(node->dev->block_size); 50 | fd_list[i].present = 1; 51 | 52 | if(node->dev->block_size != 0) 53 | read_fs(node, calc_blk_offset(node->dev->block_size, offset), fd_list[i].buffer); 54 | 55 | fd_list[i].offset = calc_buf_offset(node->dev->block_size, offset); 56 | fd_list[i].fs_size = node->length; 57 | 58 | //vga_fmt("FD for %s created with %d byte blocks, %d byte length\n", node->name, fd_list[i].block_size, node->length); 59 | 60 | return i; 61 | } 62 | } 63 | 64 | return (uint) -1; 65 | } 66 | 67 | void fd_delete(uint fd){ 68 | if(fd >= MAX_FD) 69 | return; 70 | 71 | kfree(fd_list[fd].buffer); 72 | memset(&fd_list[fd], 0, sizeof(fd_t)); 73 | } 74 | 75 | void fd_seek(uint fd, uint offset){ 76 | if(fd >= MAX_FD) 77 | return; 78 | 79 | fd_flush(fd); 80 | 81 | fd_list[fd].block = calc_blk_offset(fd_list[fd].node->dev->block_size, offset); 82 | fd_list[fd].offset = calc_buf_offset(fd_list[fd].node->dev->block_size, offset); 83 | } 84 | 85 | struct dirent* fd_readdir(uint fd){ 86 | fs_node_t* node = fd_lookup(fd); 87 | if(node == NULL) 88 | return NULL; 89 | 90 | return readdir_fs(node, fd_list[fd].offset++); 91 | } 92 | 93 | uint fd_read(uint fd, uint size, char* buffer){ 94 | fs_node_t* node = fd_lookup(fd); 95 | if(node == NULL) 96 | return NULL; 97 | 98 | int i, status; 99 | char read; 100 | 101 | if(node->dev->block_size == 0){ //Instant update device (stdout etc.) 102 | for(i = 0; i < size; i++) 103 | status = node->read_blk(node, 0, &buffer[i]); 104 | } 105 | 106 | else 107 | for(i = 0; i < size; i++){ 108 | status = fd_readch(fd, &read); 109 | buffer[i] = read; 110 | } 111 | 112 | return status; 113 | } 114 | 115 | uint fd_write(uint fd, uint size, char* buffer){ 116 | fs_node_t* node = fd_lookup(fd); 117 | if(node == NULL) 118 | return NULL; 119 | 120 | int i, status; 121 | 122 | if(node->dev->block_size == 0){ //Instant update device (stdout etc.) 123 | for(i = 0; i < size; i++) 124 | status = node->write_blk(node, 0, &buffer[i]); 125 | } 126 | 127 | else{ 128 | for(i = 0; i < size; i++) 129 | status = fd_writech(fd, &buffer[i]); 130 | } 131 | 132 | return status; 133 | 134 | } 135 | 136 | size_t calc_total_size(uint fd){ 137 | return (fd_list[fd].block * fd_list[fd].block_size) + fd_list[fd].offset; 138 | } 139 | 140 | uint fd_readch(uint fd, char* c){ 141 | if(fd >= MAX_FD){ 142 | WARN("bad file descriptor") 143 | return (uint) -1; 144 | } 145 | 146 | fd_t* desc = &fd_list[fd]; 147 | *c = desc->buffer[desc->offset++]; 148 | 149 | if(calc_blk_offset(desc->block_size, desc->fs_size) == desc->block) 150 | if(calc_buf_offset(desc->block_size, desc->fs_size) <= desc->offset){ 151 | WARN("hit buffer end") 152 | return (uint) -1; 153 | } 154 | 155 | if(desc->offset >= desc->block_size){ 156 | desc->offset = 0; 157 | desc->block++; 158 | desc->node->read_blk(desc->node, desc->block, desc->buffer); 159 | } 160 | 161 | return 0; 162 | } 163 | 164 | uint fd_writech(uint fd, char* c){ 165 | if(fd >= MAX_FD) 166 | return (uint) -1; 167 | 168 | fd_t* desc = &fd_list[fd]; 169 | desc->buffer[desc->offset++] = *c; 170 | 171 | if(desc->offset >= desc->block_size){ 172 | desc->offset = 0; 173 | desc->node->write_blk(desc->node, desc->block, desc->buffer); 174 | desc->block++; 175 | } 176 | 177 | return 0; 178 | } 179 | 180 | uint fd_flush(uint fd){ 181 | if(fd >= MAX_FD) 182 | return (uint) -1; 183 | 184 | fd_t* desc = &fd_list[fd]; 185 | desc->node->length = calc_total_size(fd); 186 | 187 | if(desc->block_size == 0) 188 | return 0; 189 | 190 | return desc->node->write_blk(desc->node, desc->block, desc->buffer); 191 | } 192 | 193 | uint fd_stat(uint fd, struct stat* buffer){ 194 | fs_node_t* node = fd_lookup(fd); 195 | if(node == NULL) 196 | return (uint) -1; 197 | 198 | buffer->st_size = node->length; 199 | buffer->st_ino = node->inode; 200 | 201 | return 0; 202 | } 203 | 204 | uint fd_offset(uint fd){ 205 | if(fd >= MAX_FD) 206 | return 0; 207 | 208 | return fd_list[fd].offset; 209 | } 210 | -------------------------------------------------------------------------------- /src/file.c: -------------------------------------------------------------------------------- 1 | #include "common.h" 2 | #include "monitor.h" 3 | #include "file.h" 4 | #include "vfs.h" 5 | #include "deepfat.h" 6 | #include "fd.h" 7 | #include "fat.h" 8 | 9 | FILE kfopen(char* path, uint offset){ 10 | fs_node_t* node = fs_path(df_root, path); 11 | 12 | if(node == NULL){ 13 | node = vfs_touch(df_root, path); 14 | 15 | if(node == NULL) 16 | return (FILE) -1; 17 | } 18 | 19 | return fd_create(node, offset); 20 | } 21 | 22 | void kfclose(FILE file){ 23 | fd_flush(file); 24 | fd_delete(file); 25 | } 26 | 27 | uint kfreadchar(FILE file, char* c){ 28 | return fd_readch(file, c); 29 | } 30 | 31 | uint kfwritechar(FILE file, char* c){ 32 | return fd_writech(file, c); 33 | } 34 | 35 | uint kfread(FILE file, uint size, char* buffer){ 36 | return fd_read(file, size, buffer); 37 | } 38 | 39 | uint kfwrite(FILE file, uint size, char* buffer){ 40 | int err = fd_write(file, size, buffer); 41 | return err; 42 | } 43 | 44 | uint kfstat(FILE file, struct stat* buffer){ 45 | return fd_stat(file, buffer); 46 | } 47 | 48 | uint kstat(char* path, struct stat* buffer){ 49 | fs_node_t* node = fs_path(df_root, path); 50 | 51 | if(node == NULL) 52 | return (uint) -1; 53 | 54 | buffer->st_ino = node->inode; 55 | buffer->st_size = node->length; 56 | 57 | return 0; 58 | } 59 | 60 | uint klseek(FILE file, uint offset, uint direction){ 61 | struct stat status; 62 | uint err = fd_stat(file, &status); 63 | 64 | if(err != 0) 65 | return (uint) -1; 66 | 67 | switch(direction){ 68 | case SEEK_SET: 69 | fd_seek(file, offset); 70 | break; 71 | case SEEK_CUR: 72 | fd_seek(file, fd_offset(file) + offset); 73 | break; 74 | case SEEK_END: 75 | fd_seek(file, status.st_size + offset); 76 | break; 77 | 78 | default: 79 | return (uint) -1; 80 | } 81 | 82 | return 0; 83 | } 84 | 85 | void kfflush(FILE file){ 86 | fd_flush(file); 87 | } 88 | -------------------------------------------------------------------------------- /src/flat.c: -------------------------------------------------------------------------------- 1 | #include "common.h" 2 | #include "virtix_page.h" 3 | #include "virtix_proc.h" 4 | #include "kheap.h" 5 | 6 | #define HANG() cli(); \ 7 | hlt(); 8 | 9 | virtix_proc_t* flat_load_bin(void* addr){ 10 | cli(); 11 | virtix_proc_t* proc = mk_empty_proc(); 12 | proc->registers.useresp = 0; 13 | proc->registers.eip = 0xF0000000; 14 | 15 | proc->name = "FLAT_BIN"; 16 | 17 | unsigned int mem = (unsigned int) kmalloc_a(PAGE_S); 18 | vpage_map_user(proc->cr3, mem, 0xF0000000); 19 | memcpy((void*) mem, (void*) addr, 1024); 20 | 21 | sti(); 22 | return proc; 23 | } 24 | -------------------------------------------------------------------------------- /src/fs.c: -------------------------------------------------------------------------------- 1 | #include "fs.h" 2 | #include "common.h" 3 | #include "kheap.h" 4 | #include "monitor.h" 5 | #include "kernel.h" 6 | 7 | directory_t* fs_root = (directory_t*) 0; 8 | unsigned int size = 0; 9 | 10 | void mnt_initrd(unsigned int ptr){ 11 | unsigned int address = *((unsigned int*) ptr); 12 | size = *((unsigned int*) address); 13 | 14 | unsigned int magic_header = *(unsigned int*)(address + 4); 15 | unsigned int magic_footer = *(unsigned int*)(address + size - 4); 16 | 17 | ASSERT((magic_footer == FFS_MAGIC) && (magic_header == FFS_MAGIC)); 18 | 19 | fs_root = (directory_t*) kmalloc(sizeof(directory_t)); 20 | fs_root->start = address; 21 | 22 | unsigned int num_files = *(unsigned int*)(address + 8); 23 | fs_root->num_files = num_files; 24 | 25 | file_t** files_list = (file_t**) kmalloc(sizeof(file_t*) * num_files); 26 | 27 | int i; 28 | for(i = 0; i < num_files; i++){ 29 | file_t* new_file = (file_t*) kmalloc(sizeof(file_t)); 30 | files_list[i] = new_file; 31 | 32 | new_file->name = (char*) (address + 12 + (i * FFS_ENTRY_SIZE)); 33 | 34 | vga_puts("CREATING: "); 35 | vga_puts(new_file->name); 36 | vga_putc('\t'); 37 | 38 | 39 | new_file->offset = *((unsigned int*) (address + 12 + (i * FFS_ENTRY_SIZE) + 128)); 40 | vga_puts("OFFSET: "); 41 | vga_puts_hex(new_file->offset); 42 | vga_putc('\t'); 43 | 44 | 45 | new_file->size = *((unsigned int*) (address + 12 + (i * FFS_ENTRY_SIZE) + 128 + 4)); 46 | vga_puts("SIZE: "); 47 | vga_puts_hex(new_file->size); 48 | vga_putc('\n'); 49 | 50 | new_file->data = (unsigned char*) (address + new_file->offset); 51 | } 52 | 53 | fs_root->files = files_list; 54 | } 55 | 56 | int is_file(char* name){ 57 | int i; 58 | for(i = 0; i < fs_root->num_files; i++){ 59 | // vga_puts("SEARCHING: "); vga_puts(fs_root->files[i]->name); vga_puts("\n"); 60 | if(!strcmp(fs_root->files[i]->name, name)) 61 | return 1; 62 | } 63 | 64 | return 0; 65 | } 66 | 67 | unsigned int get_file_size(char* name){ 68 | ASSERT(is_file(name)); 69 | 70 | int i; 71 | for(i = 0; i < fs_root->num_files; i++) 72 | if(!strcmp(fs_root->files[i]->name, name)) 73 | return fs_root->files[i]->size; 74 | 75 | return 0; 76 | } 77 | 78 | unsigned char* get_file_data(char* name){ 79 | ASSERT(is_file(name)); 80 | 81 | int i; 82 | for(i = 0; i < fs_root->num_files; i++) 83 | if(!strcmp(fs_root->files[i]->name, name)) 84 | return fs_root->files[i]->data; 85 | 86 | return 0; 87 | } 88 | -------------------------------------------------------------------------------- /src/header/ata.h: -------------------------------------------------------------------------------- 1 | #ifndef ATA_H 2 | #define ATA_H 3 | 4 | #include "common.h" 5 | 6 | #define ATA_PRIMARY_IO 0x1F0 7 | #define ATA_SECONDARY_IO 0x170 8 | 9 | #define ATA_CMD_READ_PIO 0x20 10 | #define ATA_CMD_READ_PIO_EXT 0x24 11 | #define ATA_CMD_READ_DMA 0xC8 12 | #define ATA_CMD_READ_DMA_EXT 0x25 13 | #define ATA_CMD_WRITE_PIO 0x30 14 | #define ATA_CMD_WRITE_PIO_EXT 0x34 15 | #define ATA_CMD_WRITE_DMA 0xCA 16 | #define ATA_CMD_WRITE_DMA_EXT 0x35 17 | #define ATA_CMD_CACHE_FLUSH 0xE7 18 | #define ATA_CMD_CACHE_FLUSH_EXT 0xEA 19 | #define ATA_CMD_PACKET 0xA0 20 | #define ATA_CMD_IDENTIFY_PACKET 0xA1 21 | #define ATA_CMD_IDENTIFY 0xEC 22 | 23 | #define IDE_ATA 0x00 24 | #define IDE_ATAPI 0x01 25 | 26 | #define ATA_IDENT_DEVICETYPE 0 27 | #define ATA_IDENT_CYLINDERS 2 28 | #define ATA_IDENT_HEADS 6 29 | #define ATA_IDENT_SECTORS 12 30 | #define ATA_IDENT_SERIAL 20 31 | #define ATA_IDENT_MODEL 54 32 | #define ATA_IDENT_CAPABILITIES 98 33 | #define ATA_IDENT_FIELDVALID 106 34 | #define ATA_IDENT_MAX_LBA 120 35 | #define ATA_IDENT_COMMANDSETS 164 36 | #define ATA_IDENT_MAX_LBA_EXT 200 37 | 38 | #define ATA_SR_BSY 0x80 39 | #define ATA_SR_DRDY 0x40 40 | #define ATA_SR_DF 0x20 41 | #define ATA_SR_DSC 0x10 42 | #define ATA_SR_DRQ 0x08 43 | #define ATA_SR_CORR 0x04 44 | #define ATA_SR_IDX 0x02 45 | #define ATA_SR_ERR 0x01 46 | 47 | #define ATA_IDENT_DEVICETYPE 0 48 | #define ATA_IDENT_CYLINDERS 2 49 | #define ATA_IDENT_HEADS 6 50 | #define ATA_IDENT_SECTORS 12 51 | #define ATA_IDENT_SERIAL 20 52 | #define ATA_IDENT_MODEL 54 53 | #define ATA_IDENT_CAPABILITIES 98 54 | #define ATA_IDENT_FIELDVALID 106 55 | #define ATA_IDENT_MAX_LBA 120 56 | #define ATA_IDENT_COMMANDSETS 164 57 | #define ATA_IDENT_MAX_LBA_EXT 200 58 | #define IDE_ATA 0x00 59 | #define IDE_ATAPI 0x01 60 | #define ATA_MASTER 0x00 61 | #define ATA_SLAVE 0x01 62 | #define ATA_REG_DATA 0x00 63 | #define ATA_REG_ERROR 0x01 64 | #define ATA_REG_FEATURES 0x01 65 | #define ATA_REG_SECCOUNT0 0x02 66 | #define ATA_REG_LBA0 0x03 67 | #define ATA_REG_LBA1 0x04 68 | #define ATA_REG_LBA2 0x05 69 | #define ATA_REG_HDDEVSEL 0x06 70 | #define ATA_REG_COMMAND 0x07 71 | #define ATA_REG_STATUS 0x07 72 | #define ATA_REG_SECCOUNT1 0x08 73 | #define ATA_REG_LBA3 0x09 74 | #define ATA_REG_LBA4 0x0A 75 | #define ATA_REG_LBA5 0x0B 76 | #define ATA_REG_CONTROL 0x0C 77 | #define ATA_REG_ALTSTATUS 0x0C 78 | #define ATA_REG_DEVADDRESS 0x0D 79 | 80 | #define ATA_PRIMARY 0x00 81 | #define ATA_SECONDARY 0x01 82 | 83 | #define ATA_READ 0x00 84 | #define ATA_WRITE 0x013 85 | 86 | #define ATA_MASTER_SEL 0xA0 87 | #define ATA_SLAVE_SEL 0xB0 88 | 89 | void select_ata(uchar bus, uint master); //Sets controller to given drive 90 | uchar ident_ata(uchar bus, uchar drive); //Checks that current drive is valid ATA 91 | 92 | void ata_wait(ushort io); //Proper 400ns delay 93 | void ata_poll(ushort io); //Polls until disk is ready for next command after 400ns delay 94 | 95 | void ata_read_block(ushort* buffer, uint lba); //Read block into buffer from ATA 96 | void ata_write_block(ushort* buffer, uint lba); //Write block from buffer to ATA 97 | void ata_read_blocks(ushort* buffer, uint lba, uint length); 98 | void ata_write_blocks(ushort* buffer, uint lba, uint length); 99 | 100 | void init_ata(); 101 | 102 | #endif 103 | -------------------------------------------------------------------------------- /src/header/clock.h: -------------------------------------------------------------------------------- 1 | #ifndef CLOCK_H 2 | #define CLOCK_H 3 | 4 | #include "common.h" 5 | #include "isr.h" 6 | 7 | typedef void (*clock_handler_t) (registers_t* regs); 8 | 9 | void start_timer(unsigned int frequency, clock_handler_t handler); 10 | void init_virtix_clock(); 11 | uint get_time(); 12 | void sleep(uint seconds); 13 | void msleep(uint mseconds); 14 | void init_unix_time(); 15 | 16 | void virtix_clock(registers_t* regs); 17 | 18 | uint get_year(); 19 | uint get_month(); 20 | uint get_day(); 21 | uint get_hour(); 22 | uint get_minute(); 23 | uint get_seconds(); 24 | 25 | #define CMOS_CMD 0x70 26 | #define CMOS_DATA 0x71 27 | #define CMOS_CMD_STAT 0x0A 28 | #define RTC_SECOND 0x00 29 | #define RTC_MINUTE 0x02 30 | #define RTC_HOUR 0x04 31 | #define RTC_DAY 0x07 32 | #define RTC_MONTH 0x08 33 | #define RTC_YEAR 0x09 34 | #define RTC_REG_A 0x0A 35 | #define RTC_REG_B 0x0B 36 | 37 | #define RTC_TIME_24 2 38 | #define RTC_MODE_BINARY 4 39 | 40 | #endif 41 | -------------------------------------------------------------------------------- /src/header/common.h: -------------------------------------------------------------------------------- 1 | #ifndef COMMON_H 2 | #define COMMON_H 3 | 4 | typedef unsigned int u32int; 5 | typedef int s32int; 6 | typedef unsigned short u16int; 7 | typedef short s16int; 8 | typedef unsigned char u8int; 9 | typedef char s8int; 10 | typedef int size_t; 11 | typedef unsigned int uint; 12 | typedef unsigned char uchar; 13 | typedef unsigned short ushort; 14 | 15 | #define NULL 0 16 | #define FALSE 0 17 | #define TRUE (!FALSE) 18 | 19 | typedef int bool; 20 | #define false 0 21 | #define true (!false) 22 | 23 | void outb(unsigned short port, unsigned char value); 24 | void outw(ushort port, ushort value); 25 | unsigned char inb(unsigned short port); 26 | ushort inw(ushort port); 27 | void* memset(void* s, int c, size_t n); 28 | void* memcpy(void* dest, const void* src, size_t n); 29 | 30 | size_t strlen(char* str); 31 | int strcmp(char* str1, char* str2); 32 | 33 | void dump_struct(void* structure, size_t bytes); 34 | 35 | void panic(char* msg, char* file, unsigned int line); 36 | #define PANIC(msg) panic(msg, __FILE__, __LINE__) 37 | #define ASSERT(e) ((e) ? (void) 0 : PANIC("ASSERTION FAILED:\n\n" #e)) 38 | 39 | #endif 40 | -------------------------------------------------------------------------------- /src/header/cpu.h: -------------------------------------------------------------------------------- 1 | #ifndef CPU_H 2 | #define CPU_H 3 | 4 | //ONLY CALL THESE ONCE PAGING IS ACTIVATED 5 | //Otherwise, there isn't any fault protection if CPUID isn't available 6 | 7 | #define CPU_FEATURE_FPU 1 8 | 9 | char* cpu_name(); //Return the CPU name from CPUID 10 | uint cpu_features(); //Get the EDX feature string from CPUID 11 | void cpu_check_fpu(); //Panic if there isn't an FPU 12 | 13 | #endif 14 | -------------------------------------------------------------------------------- /src/header/deepfat.h: -------------------------------------------------------------------------------- 1 | #ifndef DEEPFAT_H 2 | #define DEEPFAT_H 3 | 4 | #include "common.h" 5 | #include "vfs.h" 6 | #include "fat.h" 7 | 8 | //Root of the FS 9 | extern struct fs_node* df_root; 10 | 11 | void init_deepfat(); 12 | 13 | //VFS driver interfaces 14 | uint df_read_blk (struct fs_node* node, uint offset, uchar* buffer); 15 | uint df_write_blk (struct fs_node* node, uint offset, uchar* buffer); 16 | uint df_open (struct fs_node* node, uint index); 17 | void df_close (struct fs_node* node); 18 | 19 | struct dirent* df_readdir(struct fs_node* node, uint index); 20 | struct fs_node* df_finddir(struct fs_node* node, char* name); 21 | 22 | //Convert DF inode to FAT filename 23 | char* get_fat_name(uint inode); 24 | 25 | //Utilities for rapid file deployment 26 | struct fs_node* mk_empty_node(); 27 | struct fs_node* mk_empty_fnode(); 28 | struct fs_node* mk_empty_dnode(); 29 | 30 | //For saving files at runtime 31 | char* df_mk_name(); 32 | fat_dir_t* df_new_file(); 33 | void df_sync(); 34 | 35 | #endif 36 | -------------------------------------------------------------------------------- /src/header/descriptor_tables.h: -------------------------------------------------------------------------------- 1 | #ifndef DESC_TABLE_H 2 | #define DESC_TABLE_H 3 | 4 | struct gdt_entry_struct{ 5 | unsigned short limit_low; 6 | unsigned short base_low; 7 | u8int base_middle; 8 | u8int access; 9 | u8int granularity; 10 | u8int base_high; 11 | }__attribute__((packed)); 12 | typedef struct gdt_entry_struct gdt_entry_t; 13 | 14 | struct gdt_ptr_struct{ 15 | unsigned short limit; 16 | unsigned int base; 17 | }__attribute__((packed)); 18 | typedef struct gdt_ptr_struct gdt_ptr_t; 19 | 20 | struct idt_entry_struct{ 21 | unsigned short base_lo; 22 | unsigned short sel; 23 | u8int always0; 24 | u8int flags; 25 | unsigned short base_hi; 26 | }__attribute__((packed)); 27 | typedef struct idt_entry_struct idt_entry_t; 28 | 29 | struct idt_ptr_struct{ 30 | unsigned short limit; 31 | unsigned int base; 32 | }__attribute__((packed)); 33 | typedef struct idt_ptr_struct idt_ptr_t; 34 | 35 | // A struct describing a Task State Segment. 36 | struct tss_entry_struct 37 | { 38 | unsigned int prev_tss; // The previous TSS - if we used hardware task switching this would form a linked list. 39 | unsigned int esp0; // The stack pointer to load when we change to kernel mode. 40 | unsigned int ss0; // The stack segment to load when we change to kernel mode. 41 | unsigned int esp1; // Unused... 42 | unsigned int ss1; 43 | unsigned int esp2; 44 | unsigned int ss2; 45 | unsigned int cr3; 46 | unsigned int eip; 47 | unsigned int eflags; 48 | unsigned int eax; 49 | unsigned int ecx; 50 | unsigned int edx; 51 | unsigned int ebx; 52 | unsigned int esp; 53 | unsigned int ebp; 54 | unsigned int esi; 55 | unsigned int edi; 56 | unsigned int es; // The value to load into ES when we change to kernel mode. 57 | unsigned int cs; // The value to load into CS when we change to kernel mode. 58 | unsigned int ss; // The value to load into SS when we change to kernel mode. 59 | unsigned int ds; // The value to load into DS when we change to kernel mode. 60 | unsigned int fs; // The value to load into FS when we change to kernel mode. 61 | unsigned int gs; // The value to load into GS when we change to kernel mode. 62 | unsigned int ldt; // Unused... 63 | unsigned short trap; 64 | unsigned short iomap_base; 65 | 66 | } __attribute__((packed)); 67 | 68 | typedef struct tss_entry_struct tss_t; 69 | 70 | 71 | void init_descriptor_tables(); 72 | 73 | extern void isr0(); 74 | extern void isr1(); 75 | extern void isr2(); 76 | extern void isr3(); 77 | extern void isr4(); 78 | extern void isr5(); 79 | extern void isr6(); 80 | extern void isr7(); 81 | extern void isr8(); 82 | extern void isr9(); 83 | extern void isr10(); 84 | extern void isr11(); 85 | extern void isr12(); 86 | extern void isr13(); 87 | extern void isr14(); 88 | extern void isr15(); 89 | extern void isr16(); 90 | extern void isr17(); 91 | extern void isr18(); 92 | extern void isr19(); 93 | extern void isr20(); 94 | extern void isr21(); 95 | extern void isr22(); 96 | extern void isr23(); 97 | extern void isr24(); 98 | extern void isr25(); 99 | extern void isr26(); 100 | extern void isr27(); 101 | extern void isr28(); 102 | extern void isr29(); 103 | extern void isr30(); 104 | extern void isr31(); 105 | extern void isr0x80(); 106 | 107 | extern void irq0(); 108 | extern void irq1(); 109 | extern void irq2(); 110 | extern void irq3(); 111 | extern void irq4(); 112 | extern void irq5(); 113 | extern void irq6(); 114 | extern void irq7(); 115 | extern void irq8(); 116 | extern void irq9(); 117 | extern void irq10(); 118 | extern void irq11(); 119 | extern void irq12(); 120 | extern void irq13(); 121 | extern void irq14(); 122 | extern void irq15(); 123 | 124 | void set_kernel_stack(unsigned int stack); 125 | 126 | #endif 127 | -------------------------------------------------------------------------------- /src/header/dev.h: -------------------------------------------------------------------------------- 1 | #ifndef DEV_H 2 | #define DEV_H 3 | 4 | #include "common.h" 5 | 6 | struct dev; 7 | typedef struct fs_node fs_node_t; 8 | 9 | typedef uint (*read_block_t) (fs_node_t*, uint, uchar*); 10 | typedef uint (*write_block_t) (fs_node_t*, uint, uchar*); 11 | 12 | typedef struct dev{ 13 | char name[128]; 14 | size_t block_size; 15 | read_block_t read; 16 | write_block_t write; 17 | 18 | uchar bus; 19 | uchar drive; 20 | } dev_t; 21 | 22 | void mkdev(char* name, read_block_t read, write_block_t write); 23 | 24 | uint dev_read(fs_node_t* dev, uint offset, char* buffer); 25 | uint dev_write(fs_node_t* dev, uint offset, char* buffer); 26 | 27 | #endif 28 | -------------------------------------------------------------------------------- /src/header/disasm.h: -------------------------------------------------------------------------------- 1 | #ifndef DISASM_H 2 | #define DISASM_H 3 | #include "vproc.h" 4 | 5 | void disasm(vproc_t* proc, var address); 6 | void stack_dump(vproc_t* proc); 7 | void data_dump(vproc_t* proc); 8 | void regs_dump(vproc_t* proc); 9 | 10 | #endif 11 | -------------------------------------------------------------------------------- /src/header/elf.h: -------------------------------------------------------------------------------- 1 | #ifndef ELF_H 2 | #define ELF_H 3 | 4 | #include "common.h" 5 | #include "virtix_proc.h" 6 | 7 | typedef unsigned short elf32_half; 8 | typedef unsigned int elf32_offs; 9 | typedef unsigned int elf32_addr; 10 | typedef unsigned int elf32_word; 11 | typedef int elf32_sword; 12 | 13 | #define ELF_NIDENT 16 14 | 15 | typedef struct { 16 | unsigned char e_ident[ELF_NIDENT]; 17 | elf32_half e_type; 18 | elf32_half e_machine; 19 | elf32_word e_version; 20 | elf32_addr e_entry; 21 | elf32_offs e_phoff; 22 | elf32_offs e_shoff; 23 | elf32_word e_flags; 24 | elf32_half e_ehsize; 25 | elf32_half e_phentsize; 26 | elf32_half e_phnum; 27 | elf32_half e_shentsize; 28 | elf32_half e_shnum; 29 | elf32_half e_shstrndx; 30 | } elf32_ehdr; 31 | 32 | enum elf_ident { 33 | EI_MAG0 = 0, // 0x7F 34 | EI_MAG1 = 1, // 'E' 35 | EI_MAG2 = 2, // 'L' 36 | EI_MAG3 = 3, // 'F' 37 | EI_CLASS = 4, // Architecture (32/64) 38 | EI_DATA = 5, // Byte Order 39 | EI_VERSION = 6, // ELF Version 40 | EI_OSABI = 7, // OS Specific 41 | EI_ABIVERSION = 8, // OS Specific 42 | EI_PAD = 9 // Padding 43 | }; 44 | 45 | #define ELFMAG0 0x7F 46 | #define ELFMAG1 'E' 47 | #define ELFMAG2 'L' 48 | #define ELFMAG3 'F' 49 | 50 | #define ELFDATA2LSB (1) 51 | #define ELFCLASS32 (1) 52 | 53 | enum elf_type { 54 | ET_NONE = 0, // Unkown Type 55 | ET_REL = 1, // Relocatable File 56 | ET_EXEC = 2 // Executable File 57 | }; 58 | 59 | #define EM_386 (3) // x86 Machine Type 60 | #define EV_CURRENT (1) // ELF Current Version 61 | #define ELF_RELOC_ERR 0xFFFFFFFF 62 | 63 | typedef struct { 64 | elf32_word sh_name; 65 | elf32_word sh_type; 66 | elf32_word sh_flags; 67 | elf32_addr sh_addr; 68 | elf32_offs sh_offset; 69 | elf32_word sh_size; 70 | elf32_word sh_link; 71 | elf32_word sh_info; 72 | elf32_word sh_addralign; 73 | elf32_word sh_entsize; 74 | } elf32_shdr; 75 | 76 | 77 | enum sht_types { 78 | SHT_NULL = 0, // Null section 79 | SHT_PROGBITS = 1, // Program information 80 | SHT_SYMTAB = 2, // Symbol table 81 | SHT_STRTAB = 3, // String table 82 | SHT_RELA = 4, // Relocation (w/ addend) 83 | SHT_NOBITS = 8, // Not present in file 84 | SHT_REL = 9, // Relocation (no addend) 85 | }; 86 | 87 | enum sht_attributes { 88 | SHF_WRITE = 0x01, // Writable section 89 | SHF_ALLOC = 0x02 // Exists in memory 90 | }; 91 | 92 | typedef struct { 93 | elf32_word st_name; 94 | elf32_addr st_value; 95 | elf32_word st_size; 96 | unsigned char st_info; 97 | unsigned char st_other; 98 | elf32_half st_shndx; 99 | } elf32_sym; 100 | 101 | #define ELF32_ST_BIND(INFO) ((INFO) >> 4) 102 | #define ELF32_ST_TYPE(INFO) ((INFO) & 0x0F) 103 | 104 | #define SHN_UNDEF 0 105 | #define SHN_LORESERVE 0xff00 106 | #define SHN_LOPROC 0xff00 107 | #define SHN_HIPROC 0xff1f 108 | #define SHN_ABS 0xfff1 109 | #define SHN_COMMON 0xfff2 110 | #define SHN_HIRESERVE 0xffff 111 | 112 | enum stt_bindings { 113 | STB_LOCAL = 0, // Local scope 114 | STB_GLOBAL = 1, // Global scope 115 | STB_WEAK = 2 // Weak, (ie. __attribute__((weak))) 116 | }; 117 | 118 | enum stt_types { 119 | STT_NOTYPE = 0, // No type 120 | STT_OBJECT = 1, // Variables, arrays, etc. 121 | STT_FUNC = 2 // Methods or functions 122 | }; 123 | 124 | typedef struct { 125 | elf32_addr r_offset; 126 | elf32_word r_info; 127 | } elf32_rel; 128 | 129 | typedef struct { 130 | elf32_addr r_offset; 131 | elf32_word r_info; 132 | elf32_sword r_addend; 133 | } elf32_rela; 134 | 135 | #define ELF32_R_SYM(INFO) ((INFO) >> 8) 136 | #define ELF32_R_TYPE(INFO) ((u8int)(INFO)) 137 | 138 | enum rtt_Types { 139 | R_386_NONE = 0, // No relocation 140 | R_386_32 = 1, // Symbol + Offset 141 | R_386_PC32 = 2 // Symbol + Offset - Section Offset 142 | }; 143 | 144 | typedef struct { 145 | elf32_word p_type; 146 | elf32_offs p_offset; 147 | elf32_addr p_vaddr; 148 | elf32_addr p_paddr; 149 | elf32_word p_filesz; 150 | elf32_word p_memsz; 151 | elf32_word p_flags; 152 | elf32_word p_align; 153 | } elf32_phdr; 154 | 155 | #define DO_386_32(S, A) ((S) + (A)) 156 | #define DO_386_PC32(S, A, P) ((S) + (A) - (P)) 157 | 158 | int validate_elf(void* data); 159 | virtix_proc_t* elf_load(void* elf_data); 160 | 161 | #endif 162 | -------------------------------------------------------------------------------- /src/header/exec.h: -------------------------------------------------------------------------------- 1 | #ifndef EXEC_H 2 | #define EXEC_H 3 | 4 | #include "common.h" 5 | 6 | uint kexec(char* path); 7 | uint kexec_pipes(char* path, char* stdin, char* stdout, char* stderr); 8 | uint uexec(char* path); //DO NOT CALL DIRECTLY, only for interrupt use 9 | 10 | #endif 11 | -------------------------------------------------------------------------------- /src/header/fat.h: -------------------------------------------------------------------------------- 1 | #ifndef FAT_H 2 | #define FAT_H 3 | 4 | typedef struct{ 5 | uchar jmp[3]; //jmp short NOP 6 | uchar oem_ident[8]; //Short OEM string 7 | 8 | ushort bytes_per_sector; 9 | uchar sectors_per_cluster; 10 | 11 | ushort number_reserved; //The reserved sectors for boot 12 | uchar number_fats; //Usually two 13 | ushort dir_size; 14 | 15 | ushort short_num_sectors; //If zero, need to check other value 16 | uchar media_type; 17 | ushort sectors_per_fat; 18 | ushort sectors_per_track; 19 | 20 | ushort number_heads; 21 | uint number_hidden; 22 | uint long_num_sectors; //Used if the other value is zero 23 | }__attribute__((packed)) fat_header_t; 24 | 25 | typedef struct{ 26 | char name[8]; 27 | char extension[3]; 28 | 29 | uchar attributes; 30 | uchar reserved; 31 | 32 | uchar creation_second; 33 | ushort creation_time; 34 | ushort creation_date; 35 | ushort accessed_date; 36 | 37 | ushort cluster_high; 38 | 39 | ushort mod_time; 40 | ushort mod_date; 41 | 42 | ushort cluster_low; 43 | 44 | uint bytes; 45 | }__attribute__((packed)) fat_dir_t; 46 | 47 | extern fat_header_t fat_header; 48 | 49 | void init_fat(); 50 | uint cluster_to_lba(uint cluster); 51 | void disp_bpb(); 52 | void disp_fat_dir(); 53 | 54 | fat_dir_t* fat_search(char* fat_name); 55 | 56 | void* fat_load_full(char* fat_name); 57 | fat_dir_t* fat_dir_search(char* fat_name); 58 | char* fat_name_conv(char* actual); 59 | 60 | fat_dir_t* fat_create(char* name); //Find and create free entry 61 | void fat_delete(char* name); //Remove entry and clusters 62 | 63 | uint fat_read_block(char* name, uint offset, uchar* buffer); 64 | uint fat_write_block(char* name, uint offset, uchar* buffer); 65 | uint fat_read(char* name, uint offset, uint length, char* buffer); 66 | uint fat_write(char* name, uint offset, uint length, char* buffer); 67 | ushort fat_next_cluster(); //First free cluster 68 | 69 | void fat_sync(); //Sync between ram and disk tables 70 | void update_size(fat_dir_t* entry, uint offset, uint length); //Update an entry during write 71 | 72 | #define FAT_TOTAL_SIZE (fat_header.number_fats * fat_header.sectors_per_fat) 73 | #define FAT_DIR_SIZE ((32 * fat_header.dir_size) / 512) 74 | 75 | #define CLUSTER_BSIZE (fat_header.sectors_per_cluster * 512) 76 | #define FAT_SPC (fat_header.sectors_per_cluster) 77 | 78 | #define FAT_APPEND 0 79 | #define FAT_REPLACE 1 80 | 81 | #endif 82 | -------------------------------------------------------------------------------- /src/header/fd.h: -------------------------------------------------------------------------------- 1 | #ifndef FD_H 2 | #define FD_H 3 | 4 | #include "common.h" 5 | #include "vfs.h" 6 | 7 | #define MAX_FD 16 8 | 9 | typedef struct{ 10 | char name[128]; 11 | fs_node_t* node; 12 | 13 | uint offset; 14 | uint block; 15 | size_t block_size; 16 | size_t fs_size; 17 | 18 | char* buffer; 19 | 20 | uint mode; 21 | uint present; 22 | } fd_t; 23 | 24 | void init_fd(); 25 | 26 | fs_node_t* fd_lookup(uint fd); 27 | uint fd_create(fs_node_t* node, uint offset); 28 | void fd_delete(uint fd); 29 | 30 | uint fd_offset(uint fd); 31 | 32 | void fd_seek(uint fd, uint offset); 33 | uint fd_read(uint fd, uint size, char* buffer); 34 | uint fd_write(uint fd, uint size, char* buffer); 35 | uint fd_flush(uint fd); 36 | uint fd_readch(uint fd, char* c); 37 | uint fd_writech(uint fd, char* c); 38 | struct dirent* fd_readdir(uint fd); 39 | uint fd_stat(uint fd, struct stat* buffer); 40 | 41 | #endif 42 | -------------------------------------------------------------------------------- /src/header/file.h: -------------------------------------------------------------------------------- 1 | #ifndef FILE_H 2 | #define FILE_H 3 | 4 | #include "common.h" 5 | #include "vfs.h" 6 | 7 | #define SEEK_SET 0 8 | #define SEEK_CUR 1 9 | #define SEEK_END 2 10 | 11 | typedef uint FILE; 12 | typedef uint DIR; 13 | 14 | FILE kfopen(char* path, uint offset); 15 | void kfclose(FILE file); 16 | uint kfwrite(FILE file, uint size, char* buffer); 17 | uint kfread(FILE file, uint size, char* buffer); 18 | uint kfstat(FILE file, struct stat* buffer); 19 | uint kstat(char* path, struct stat* buffer); 20 | uint klseek(FILE file, uint offset, uint direction); 21 | uint kfreadchar(FILE file, char* c); 22 | uint kfwritechar(FILE file, char* c); 23 | void kfflush(FILE file); 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /src/header/flat.h: -------------------------------------------------------------------------------- 1 | #ifndef FLAT_H 2 | #define FLAT_H 3 | 4 | #include "common.h" 5 | #include "virtix_proc.h" 6 | 7 | virtix_proc_t* flat_load_bin(void* addr); 8 | 9 | #endif 10 | -------------------------------------------------------------------------------- /src/header/fs.h: -------------------------------------------------------------------------------- 1 | #ifndef FS_H 2 | #define FS_H 3 | 4 | #undef data 5 | 6 | #define FFS_MAGIC 0x04206969 7 | #define FFS_ENTRY_SIZE (128 + 4 + 4) 8 | 9 | typedef struct file{ 10 | unsigned int offset; 11 | unsigned int size; 12 | char* name; 13 | unsigned char* data; 14 | struct file* next; 15 | } file_t; 16 | 17 | typedef struct directory{ 18 | unsigned int start; 19 | unsigned int num_files; 20 | 21 | file_t** files; 22 | } directory_t; 23 | 24 | extern directory_t* fs_root; 25 | extern unsigned int size; 26 | 27 | void mnt_initrd(unsigned int address); 28 | int is_file(char* name); 29 | unsigned int get_file_size(char* name); 30 | unsigned char* get_file_data(char* name); 31 | #endif 32 | -------------------------------------------------------------------------------- /src/header/init.h: -------------------------------------------------------------------------------- 1 | #ifndef INIT_H 2 | #define INIT_H 3 | 4 | #include "common.h" 5 | 6 | #define DEVLOAD(x) extern void x(); x(); 7 | 8 | void driver_init(); 9 | 10 | #endif 11 | -------------------------------------------------------------------------------- /src/header/isr.h: -------------------------------------------------------------------------------- 1 | #ifndef ISR_H 2 | #define ISR_H 3 | 4 | #include "common.h" 5 | 6 | extern unsigned int* istack_base; 7 | extern unsigned int stack_hold; 8 | 9 | typedef struct registers{ 10 | u32int ds; 11 | u32int edi, esi, ebp, esp, ebx, edx, ecx, eax; 12 | u32int int_no, err_code; 13 | u32int eip, cs, eflags, useresp, ss; 14 | }registers_t; 15 | 16 | typedef void (*isr_t)(registers_t*); 17 | void register_interrupt_handler(unsigned char index, isr_t handler); 18 | void cli(); 19 | void sti(); 20 | void hlt(); 21 | 22 | void register_default_handlers(); 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /src/header/kernel.h: -------------------------------------------------------------------------------- 1 | #ifndef KERNEL_H 2 | #define KERNEL_H 3 | 4 | #include "kheap.h" 5 | 6 | //extern heap_t* kheap; 7 | 8 | #endif 9 | -------------------------------------------------------------------------------- /src/header/keyboard.h: -------------------------------------------------------------------------------- 1 | #ifndef KEYBOARD_H 2 | #define KEYBOARD_H 3 | 4 | #include "common.h" 5 | 6 | void init_keyboard(); //Register the keyboard interrupt handler, etc. 7 | char getkey_scancode(); //Poll the handler for the scan code 8 | char getkey_ascii(); //Translate the scan code to ascii and return 9 | char translate_scancode(uchar scancode); 10 | 11 | //PS/2 Ports 12 | #define KEYBOARD_DATA 0x60 13 | #define KEYBOARD_CMD 0x64 14 | #define KEYBOARD_STAT 0x64 15 | 16 | //Key definitions 17 | #define RIGHTSHIFT_DOWN 0x36 18 | #define RIGHTSHIFT_UP 0xB6 19 | #define LEFTSHIFT_DOWN 0x2A 20 | #define LEFTSHIFT_UP 0xAA 21 | #define KBD_Q_DOWN 0x10 22 | #define KBD_W_DOWN 0x11 23 | #define KBD_E_DOWN 0x12 24 | #define KBD_R_DOWN 0x13 25 | #define KBD_T_DOWN 0x14 26 | #define KBD_Y_DOWN 0x15 27 | #define KBD_U_DOWN 0x16 28 | #define KBD_I_DOWN 0x17 29 | #define KBD_O_DOWN 0x18 30 | #define KBD_P_DOWN 0x19 31 | #define KBD_A_DOWN 0x1E 32 | #define KBD_S_DOWN 0x1F 33 | #define KBD_D_DOWN 0x20 34 | #define KDB_F_DOWN 0x21 35 | #define KBD_G_DOWN 0x22 36 | #define KBD_H_DOWN 0x23 37 | #define KBD_J_DOWN 0x24 38 | #define KBD_K_DOWN 0x25 39 | #define KBD_L_DOWN 0x26 40 | #define KBD_Z_DOWN 0x2C 41 | #define KBD_X_DOWN 0x2D 42 | #define KBD_C_DOWN 0x2E 43 | #define KBD_V_DOWN 0x2F 44 | #define KBD_B_DOWN 0x30 45 | #define KBD_N_DOWN 0x31 46 | #define KBD_M_DOWN 0x32 47 | #define KBD_1_DOWN 0x02 48 | #define KBD_2_DOWN 0x03 49 | #define KBD_3_DOWN 0x04 50 | #define KBD_4_DOWN 0x05 51 | #define KBD_5_DOWN 0x06 52 | #define KBD_6_DOWN 0x07 53 | #define KBD_7_DOWN 0x08 54 | #define KBD_8_DOWN 0x09 55 | #define KBD_9_DOWN 0x0A 56 | #define KBD_0_DOWN 0x0B 57 | #define KBD_MINUS_DOWN 0x0C 58 | #define KBD_PLUS_DOWN 0x0D 59 | #define KBD_BKSP_DOWN 0x0E 60 | 61 | //Special keys 62 | #define KBD_ENTER 0x1C 63 | #define KBD_SPC_DOWN 0x39 64 | 65 | //PS/2 Statuses 66 | #define KBDSTAT_ACK 0xFA 67 | #define KBDSTAT_RES 0xFE 68 | 69 | //PS/2 Commands 70 | #define KBDCMD_SETRATE 0xF3 71 | #define KBDCMD_SETSCAN 0xF0 72 | #define KBDCMD_SETNOUP 0xF9 73 | 74 | #endif 75 | -------------------------------------------------------------------------------- /src/header/kheap.h: -------------------------------------------------------------------------------- 1 | #ifndef KHEAP_H 2 | #define KHEAP_H 3 | 4 | #include "common.h" 5 | #define KHEAP_MAGIC 0x04206969 6 | #define KHEAP_MAGIC2 0xDEADBEEF 7 | 8 | #define KHEAP_END 0xFFFFDEAD 9 | 10 | #define MEM_END 0x8000000 11 | 12 | extern unsigned int end; 13 | 14 | typedef struct{ 15 | uint magic; 16 | bool free; 17 | uint size; 18 | uint magic2; 19 | } heap_header_t; 20 | 21 | typedef struct{ 22 | uint magic; 23 | uint size; 24 | uint magic2; 25 | } heap_footer_t; 26 | 27 | #define HEAP_S (sizeof(heap_header_t)) 28 | #define HEAP_TOTAL (sizeof(heap_footer_t) + HEAP_S) 29 | #define HEAP_MINIMUM 1 30 | #define HEAP_FIND_SIZE (HEAP_TOTAL + HEAP_MINIMUM) 31 | 32 | void init_kheap(); //Initialize heaps globally 33 | 34 | void* fmalloc(uint size); 35 | void* kmalloc(unsigned int size); //straight kmalloc 36 | void* kmalloc_a(unsigned int size); //page aligned kmalloc 37 | void kfree(void* ptr); //Free unused memory 38 | 39 | void* umalloc(size_t size); //Allocate in userspace 40 | void ufree(void* address); //Free in userspace 41 | 42 | void init_heap(heap_header_t* heap, size_t size); 43 | 44 | #define KHEAP_SIZE 0xFFFFF 45 | #define UHEAP_SIZE 0xFFFFF 46 | 47 | #endif 48 | -------------------------------------------------------------------------------- /src/header/kstub.h: -------------------------------------------------------------------------------- 1 | #ifndef KSTUB_H 2 | #define KSTUB_H 3 | 4 | #include "common.h" 5 | #include "vproc.h" 6 | 7 | //Services a system call to the current process 8 | var kservice(vproc_t* current, var option); 9 | 10 | //Maps a vproc to the kstub handler 11 | void map_kstub(vproc_t* stub); 12 | 13 | #endif -------------------------------------------------------------------------------- /src/header/kthread.h: -------------------------------------------------------------------------------- 1 | #ifndef KTHREAD_H 2 | #define KTHREAD_H 3 | 4 | #include "common.h" 5 | #include "virtix_proc.h" 6 | 7 | //Make a kernel thread at addr with name "name" 8 | void mk_kthread(char* name, void* addr); 9 | 10 | //Hang a kthread 11 | void kthread_hlt(); 12 | 13 | //Exit kthread 14 | void kthread_exit(); 15 | 16 | #endif -------------------------------------------------------------------------------- /src/header/loader.h: -------------------------------------------------------------------------------- 1 | #ifndef LOADER_H 2 | #define LOADER_H 3 | 4 | #include "common.h" 5 | #include "elf.h" 6 | #include "proc.h" 7 | 8 | void* bin_get_init(elf32_ehdr* header); 9 | void hook_proc(elf32_ehdr* header, PROC* proc); 10 | 11 | #endif 12 | -------------------------------------------------------------------------------- /src/header/monitor.h: -------------------------------------------------------------------------------- 1 | #ifndef MONITOR_H 2 | #define MONITOR_H 3 | 4 | #include "common.h" 5 | #include "clock.h" 6 | 7 | void vga_putc(char c); 8 | void vga_clear(); 9 | void vga_puts(char* s); 10 | void vga_puts_hex(int n); 11 | void vga_puts_dec(int n); 12 | void vga_putc_hex(char n); 13 | void vga_fmt(const char* format, ...); 14 | void vga_set_fg(uchar color); 15 | void vga_set_bg(uchar color); 16 | void vga_blink(); 17 | void vga_reset(); 18 | 19 | #define DISP(name,val) vga_puts((name));\ 20 | vga_puts(":\t");\ 21 | vga_puts_hex((val));\ 22 | vga_puts("\n"); 23 | 24 | #define NOTIFY(str) vga_set_fg(GREEN);\ 25 | vga_fmt("[%d:%d:%d] ", get_hour(), get_minute(), get_seconds());\ 26 | vga_set_fg(CYAN);\ 27 | vga_puts((char*) __FUNCTION__);\ 28 | vga_puts("(): ");\ 29 | vga_reset();\ 30 | vga_puts((str));\ 31 | vga_puts("\n"); 32 | 33 | #define WARN(str) vga_set_fg(GREEN);\ 34 | vga_fmt("[%d:%d:%d] ", get_hour(), get_minute(), get_seconds());\ 35 | vga_set_fg(RED);\ 36 | vga_puts((char*) __FUNCTION__);\ 37 | vga_puts("(): ");\ 38 | vga_reset();\ 39 | vga_puts((str));\ 40 | vga_puts("\n"); 41 | 42 | #define BLACK 0 43 | #define BLUE 1 44 | #define GREEN 2 45 | #define CYAN 3 46 | #define RED 4 47 | #define MAGENTA 5 48 | #define BROWN 6 49 | #define LIGHT_GREY 7 50 | #define DARK_GREY 8 51 | #define LIGHT_BLUE 9 52 | #define LIGHT_GREEN 10 53 | #define LIGHT_CYAN 11 54 | #define LIGHT_RED 12 55 | #define LIGHT_MAGENTA 13 56 | #define LIGHT_BROWN 14 57 | #define WHITE 15 58 | 59 | #endif 60 | -------------------------------------------------------------------------------- /src/header/multiboot.h: -------------------------------------------------------------------------------- 1 | #ifndef MULTIBOOT_H 2 | #define MULTIBOOT_H 3 | 4 | #include "common.h" 5 | 6 | #define MULTIBOOT_FLAG_MEM 1 7 | #define MULTIBOOT_FLAG_DEVICE 2 8 | #define MULTIBOOT_FLAG_CMDLINE 4 9 | #define MULTIBOOT_FLAG_MODS 8 10 | #define MULTIBOOT_FLAG_AOUT 0x10 11 | #define MULTIBOOT_FLAG_ELF 0x20 12 | #define MULTIBOOT_FLAG_MMAP 0x40 13 | #define MULTIBOOT_FLAG_CONFIG 0x80 14 | #define MULTIBOOT_FLAG_LOADER 0x100 15 | #define MULTIBOOT_FLAG_APM 0x200 16 | #define MULTIBOOT_FLAG_VBE 0x400 17 | 18 | struct multiboot{ 19 | unsigned int flags, 20 | mem_lower, 21 | mem_upper, 22 | boot_device, 23 | cmdline, 24 | mods_count, 25 | mods_addr, 26 | num, 27 | size, 28 | addr, 29 | shndx, 30 | mmap_length, 31 | mmap_addr, 32 | drives_length, 33 | drives_addr, 34 | config_table, 35 | boot_loader_name, 36 | apm_table, 37 | vbe_control_info, 38 | vbe_mode_info, 39 | vbe_mode, 40 | vbe_interface_seg, 41 | vbe_interface_off, 42 | vbe_interface_len; 43 | }__attribute__((packed)); 44 | 45 | typedef struct multiboot_header multiboot_header_t; 46 | 47 | #endif 48 | -------------------------------------------------------------------------------- /src/header/paging.h: -------------------------------------------------------------------------------- 1 | #ifndef PAGING_H 2 | #define PAGING_H 3 | 4 | #include "common.h" 5 | #include "isr.h" 6 | 7 | #define PAGE_S 0x400000 8 | 9 | extern unsigned int* current_dir; 10 | extern unsigned int* root_dir; 11 | 12 | typedef struct{ 13 | unsigned int present : 1; 14 | unsigned int rw : 1; 15 | unsigned int user : 1; 16 | unsigned int accessed : 1; 17 | unsigned int dirty : 1; 18 | unsigned int unused : 7; 19 | unsigned int frame : 20; 20 | } page_t; 21 | 22 | typedef struct{ 23 | page_t pages[1024]; 24 | } page_table_t; 25 | 26 | typedef struct{ 27 | page_table_t* tables[1024]; 28 | unsigned int tables_physical[1024]; 29 | unsigned int physical_address; 30 | } page_directory_t; 31 | 32 | /*void init_paging(); 33 | void enable_paging(); 34 | void switch_page(unsigned int* page_dir); 35 | void map_vpage_to_ppage(unsigned int vpage, unsigned int ppage); 36 | 37 | //Create new pages 38 | unsigned int* mk_page(); 39 | unsigned int* mk_page_dir(); 40 | void mmap_page(unsigned int* page, unsigned int vpage, unsigned int ppage); 41 | 42 | void page_fault(registers_t* regs); 43 | void dump_page(unsigned int* dir); 44 | */ 45 | 46 | #endif 47 | -------------------------------------------------------------------------------- /src/header/real.h: -------------------------------------------------------------------------------- 1 | #ifndef REAL_H 2 | #define REAL_H 3 | 4 | #include "common.h" 5 | 6 | //Run a 16Bit stub in real mode at 0x7C00 and then return to pmode 7 | void run_stub16(char* file); 8 | 9 | #endif 10 | -------------------------------------------------------------------------------- /src/header/sched.h: -------------------------------------------------------------------------------- 1 | #ifndef SCHED_H 2 | #define SCHED_H 3 | 4 | #include "vproc.h" 5 | 6 | //Number of processes 7 | #define SCHED_SIZE 16 8 | 9 | //Public list of vprocs that are running 10 | extern vproc_t** vproc_list; 11 | 12 | //Initialize memory for scheduler 13 | void init_sched(); 14 | 15 | //Runs all current processes in process list for one iteration 16 | var tick_all(); 17 | 18 | //Add and remove processes 19 | var mk_vproc(vproc_t* proc); 20 | var rm_vproc(vproc_t* proc); 21 | 22 | #endif 23 | -------------------------------------------------------------------------------- /src/header/signal.h: -------------------------------------------------------------------------------- 1 | #ifndef SIGNAL_H 2 | #define SIGNAL_H 3 | 4 | #define SIGABRT 0 5 | #define SIGFPE 1 6 | #define SIGILL 2 7 | #define SIGINT 3 8 | #define SIGSEGV 4 9 | #define SIGTERM 5 10 | 11 | #define NUM_SIGS 6 12 | 13 | #define SIG_ERR (-1) 14 | 15 | #include "common.h" 16 | #include "virtix_proc.h" 17 | 18 | //Code to raise an exception within a process 19 | void raise(virtix_proc_t* proc, uint signal); 20 | 21 | //Code to set an exception handler within a process 22 | void signal(virtix_proc_t* proc, uint signal, uint func); 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /src/header/single.h: -------------------------------------------------------------------------------- 1 | #ifndef SINGLE_H 2 | #define SINGLE_H 3 | 4 | #include "common.h" 5 | #include "virtix_proc.h" 6 | #include "isr.h" 7 | 8 | unsigned int sp_child(virtix_proc_t* child); //Spawn "child" in single process mode 9 | void enter_userspace(virtix_proc_t* proc); //Force CPU to run in user mode in proc 'force' 10 | void single_yield(virtix_proc_t* proc, registers_t* regs); //yield execution to another process 11 | unsigned int single_exit(registers_t* regs); //Leave process 12 | 13 | extern void hard_usermode(); //Assembly hardloading stub 14 | 15 | #endif 16 | -------------------------------------------------------------------------------- /src/header/stdarg.h: -------------------------------------------------------------------------------- 1 | #ifndef STDARG_H 2 | #define STDARG_H 3 | 4 | typedef __builtin_va_list va_list; 5 | #define va_start __builtin_va_start 6 | #define va_end __builtin_va_end 7 | #define va_arg __builtin_va_arg 8 | 9 | #endif 10 | -------------------------------------------------------------------------------- /src/header/str-util.h: -------------------------------------------------------------------------------- 1 | //This file is simply for simple, in-kernel parsing 2 | 3 | #ifndef STRUTIL_H 4 | #define STRUTIL_H 5 | 6 | #include "common.h" 7 | 8 | //Turn all spaces and newlines into \o 9 | char* prep_str(char* str); 10 | 11 | //Returns the next word in a prep_str'd string 12 | char* next_str(char* str); 13 | 14 | //Moves a string to a given destination, delimiter and all 15 | void strmov(char* dest, char* src); 16 | 17 | #endif 18 | -------------------------------------------------------------------------------- /src/header/stream.h: -------------------------------------------------------------------------------- 1 | #ifndef STREAM_H 2 | #define STREAM_H 3 | 4 | #include "common.h" 5 | 6 | typedef struct { 7 | uint block; 8 | uint offset; 9 | size_t size; 10 | char* data; 11 | } stream_t; 12 | 13 | stream_t* mk_stream(size_t size); 14 | void rm_stream; 15 | 16 | #endif 17 | -------------------------------------------------------------------------------- /src/header/syscall.h: -------------------------------------------------------------------------------- 1 | #ifndef SYSCALL_H 2 | #define SYSCALL_H 3 | 4 | #include "common.h" 5 | #include "isr.h" 6 | 7 | #define SYS_GETPID 0 8 | #define SYS_FORK 1 9 | #define SYS_EXEC 2 10 | #define SYS_OPEN 3 11 | #define SYS_WRITE 4 12 | #define SYS_READ 5 13 | 14 | void syscall_handler(registers_t regs); 15 | 16 | #endif 17 | -------------------------------------------------------------------------------- /src/header/tty.h: -------------------------------------------------------------------------------- 1 | #ifndef TTY_H 2 | #define TTY_H 3 | 4 | #include "common.h" 5 | 6 | //This uses the VGA text mode as a vt 7 | 8 | #define TTY_HEIGHT 25 9 | #define TTY_WIDTH 80 10 | 11 | extern char tty_key; 12 | 13 | void tty_init(); 14 | 15 | void tty_clear(); 16 | void tty_reset(); 17 | void tty_putc(char c); 18 | char tty_getc(); 19 | 20 | #endif 21 | -------------------------------------------------------------------------------- /src/header/userspace.h: -------------------------------------------------------------------------------- 1 | #ifndef USERSPACE_H 2 | #define USERSPACE_H 3 | 4 | #include "common.h" 5 | #include "virtix_proc.h" 6 | 7 | extern unsigned int c_err; 8 | typedef unsigned int uint; 9 | 10 | #define SYS_FORK 0 11 | #define SYS_GETPID 1 12 | #define SYS_GETENV 2 13 | #define SYS_WRITE 3 14 | #define SYS_READ 4 15 | #define SYS_CLOSE 5 16 | #define SYS_EXIT 6 17 | #define SYS_OPEN 7 18 | #define SYS_MALLOC 8 19 | #define SYS_FREE 9 20 | #define SYS_GET_ARGS 10 21 | #define SYS_LSEEK 11 22 | 23 | #define SYS_GETSTDIN 12 24 | #define SYS_GETSTDOUT 13 25 | #define SYS_GETSTDERR 14 26 | 27 | #define SYS_EXEC 15 28 | #define SYS_SBRK 16 29 | #define SYS_RAISE 17 30 | #define SYS_SIGNAL 18 31 | #define SYS_SIGEXIT 19 32 | #define SYS_WAIT 20 33 | #define SYS_GETGID 21 34 | 35 | #define SYS_GETCWD 22 36 | #define SYS_CHDIR 23 37 | #define SYS_EXECVE 24 38 | 39 | #define SYS_STAT 25 40 | #define SYS_FSTAT 26 41 | #define SYS_SYNC 27 42 | 43 | uint fork(); 44 | uint getpid(); 45 | char** get_env(); 46 | 47 | uint write(uint fid, char* buffer, size_t length); 48 | uint read(uint fid, char* buffer, size_t length); 49 | uint close(uint fid); 50 | uint open(char* path, uint offset); 51 | int sys_wait(int pid, int* status, int options); 52 | 53 | uint _exit(registers_t* regs); 54 | 55 | void init_userspace(); //Maps userspace call handler 56 | 57 | #endif 58 | -------------------------------------------------------------------------------- /src/header/vfs.h: -------------------------------------------------------------------------------- 1 | #ifndef VFS_H 2 | #define VFS_H 3 | 4 | //The aim of this header is to provide basic 5 | //POSIX VFS style operation for the OS 6 | 7 | #include "common.h" 8 | #include "dev.h" 9 | 10 | struct fs_node; 11 | 12 | typedef uint (*read_type_t) (struct fs_node*, uint, uint, char*); 13 | typedef uint (*write_type_t) (struct fs_node*, uint, uint, char*); 14 | typedef uint (*open_type_t) (struct fs_node*, uint); 15 | typedef void (*close_type_t) (struct fs_node*); 16 | 17 | typedef struct dirent* (*readdir_type_t)(struct fs_node*, uint); 18 | typedef struct fs_node* (*finddir_type_t)(struct fs_node*, char* name); 19 | 20 | typedef struct fs_node{ 21 | char name[128]; 22 | uint permissions; 23 | 24 | uint uid; 25 | uint gid; 26 | uint flags; 27 | 28 | char dos_name[16]; 29 | uint inode; 30 | uint length; 31 | 32 | dev_t* dev; 33 | 34 | open_type_t open; 35 | close_type_t close; 36 | 37 | read_block_t read_blk; 38 | write_block_t write_blk; 39 | 40 | readdir_type_t readdir; 41 | finddir_type_t finddir; 42 | 43 | struct fs_node* holds; 44 | struct fs_node* link; 45 | } fs_node_t; 46 | 47 | struct dirent{ 48 | char name[128]; 49 | uint ino; 50 | }; 51 | 52 | struct stat{ 53 | uint st_dev; 54 | uint st_ino; 55 | uint st_mode; 56 | uint st_nlink; 57 | uint st_uid; 58 | uint st_gid; 59 | uint st_rdev; 60 | uint st_size; 61 | uint st_atime; 62 | uint st_mtime; 63 | uint st_ctime; 64 | uint st_blksize; 65 | uint st_blocks; 66 | }; 67 | 68 | #define FS_FILE 1 69 | #define FS_DIRECTORY 2 70 | #define FS_CHARDEVICE 3 71 | #define FS_BLOCKDEVICE 4 72 | #define FS_PIPE 5 73 | #define FS_SYMLINK 6 74 | #define FS_MOUNTPOINT 8 75 | 76 | extern fs_node_t* root_node; 77 | 78 | uint read_fs(fs_node_t* node, uint offset, uchar* buffer); 79 | uint write_fs(fs_node_t* node, uint offset, uchar* buffer); 80 | 81 | uint open_fs(fs_node_t* node, uint offset); 82 | void close_fs(fs_node_t* node); 83 | 84 | struct dirent* readdir_fs(fs_node_t* node, uint index); 85 | fs_node_t* finddir_fs(fs_node_t* node, char* name); 86 | fs_node_t* fs_path(fs_node_t* node, char* name); 87 | fs_node_t* vfs_get_dir(fs_node_t* node, char* name); 88 | char* basename(char* path); 89 | struct dirent* readdir_generic(fs_node_t* node, uint index); 90 | 91 | fs_node_t* vfs_touch(fs_node_t* node, char* path); 92 | fs_node_t* vfs_mkdir(fs_node_t* node, char* path); 93 | 94 | void vfs_ls(char* path); 95 | 96 | #endif 97 | -------------------------------------------------------------------------------- /src/header/virtix_page.h: -------------------------------------------------------------------------------- 1 | #ifndef VIRTIX_PAGE_H 2 | #define VIRTIX_PAGE_H 3 | 4 | #include "common.h" 5 | #include "paging.h" 6 | 7 | typedef struct{ 8 | page_table_t* tables[1024]; 9 | } vpage_dir_t; 10 | 11 | extern vpage_dir_t* root_vpage_dir; 12 | 13 | #define EMPTY_TAB ((page_table_t*) 0x00000002) 14 | 15 | page_table_t* get_cr3(); //contents of cr3 register 16 | unsigned int get_cr0(); //contents of cr0 register 17 | 18 | void set_cr3(vpage_dir_t* dir); //set cr3 register 19 | void set_cr0(unsigned int new_cr0); //set cr0 register 20 | 21 | void switch_vpage_dir(vpage_dir_t* dir); //Change address space 22 | 23 | vpage_dir_t* mk_vpage_dir(); //Make empty root page dir 24 | page_table_t* mk_vpage_table(); 25 | 26 | void virtix_page_init(); //Start paging 27 | 28 | void vpage_map(vpage_dir_t* cr3, unsigned int virt, unsigned int phys); 29 | void vpage_map_user(vpage_dir_t* cr3, unsigned int virt, unsigned int phys); 30 | 31 | void convert_vpage(vpage_dir_t* kdir); //Change page to usermode 32 | 33 | void dump_page(vpage_dir_t* dir, unsigned int address); 34 | 35 | vpage_dir_t* copy_user_dir(vpage_dir_t* dir); 36 | 37 | #endif 38 | -------------------------------------------------------------------------------- /src/header/virtix_proc.h: -------------------------------------------------------------------------------- 1 | #ifndef VIRTIX_PROC_H 2 | #define VIRTIX_PROC_H 3 | 4 | #include "common.h" 5 | #include "isr.h" 6 | #include "virtix_page.h" 7 | 8 | typedef struct { 9 | unsigned int text; 10 | unsigned int bss; 11 | unsigned int data; 12 | unsigned int stack; 13 | } mmap_t; 14 | 15 | typedef struct virtix_proc { 16 | vpage_dir_t* cr3; //Memory pages 17 | registers_t registers; //Process state 18 | 19 | unsigned int pid; //Process integer ID 20 | unsigned int gid; //Process group ID 21 | char* name; //Process/program name 22 | 23 | int state; //Sleeping | running 24 | int thread; //Whether process is thread 25 | 26 | uint stdin; //Current streams 27 | uint stdout; 28 | uint stderr; 29 | 30 | uint brk; //Program break location 31 | 32 | uint handlers[6]; //Signal handling table 33 | 34 | struct virtix_proc* parent; //If child, this will be set 35 | struct virtix_proc* next; //Next process 36 | } virtix_proc_t; 37 | 38 | void scheduler(registers_t* regs); 39 | 40 | void kill_proc(unsigned int pid); //End a process 41 | unsigned int spawn_proc(virtix_proc_t* process); //Start a process 42 | void susp_proc(unsigned int pid); //Suspend a process 43 | void wake_proc(unsigned int pid); //Wake a process back up 44 | unsigned int child_proc(virtix_proc_t* process, unsigned int pid); //Sleep the process 45 | unsigned int fork_proc(unsigned int pid); //Fork the process 46 | 47 | int wait_gid(uint gid, int* status); //Tries to see if the process has died yet 48 | int wait_pid(uint pid, int* status); 49 | 50 | virtix_proc_t* pid_to_proc(unsigned int pid); //Get a process from a PID 51 | 52 | void init_procs(virtix_proc_t* proc); //maps a process handler to the PIT 53 | 54 | virtix_proc_t* mk_empty_proc(); //Make an empty (initialized) process structure 55 | 56 | void dump_proc(virtix_proc_t* proc); 57 | 58 | extern virtix_proc_t* current_proc; 59 | 60 | extern unsigned int stack_hold; 61 | 62 | #define PID_NOT_FOUND ((virtix_proc_t*) 0xFFFFFFFF) 63 | 64 | #define PROC_RUNNING 0 65 | #define PROC_ASLEEP 1 66 | 67 | #define PROC_THREAD 0 68 | #define PROC_PROC 1 69 | #define PROC_ROOT 2 70 | 71 | #define WAIT_ERROR (-1) 72 | #define WAIT_OKAY 0 73 | 74 | #endif 75 | -------------------------------------------------------------------------------- /src/header/vm-error.h: -------------------------------------------------------------------------------- 1 | #ifndef VM_ERROR_H 2 | #define VM_ERROR_H 3 | #include "vproc.h" 4 | 5 | #define VMERR (-1) 6 | 7 | //Runtime error 8 | int error(char* message, vproc_t* process, int e_offs); 9 | //Internal error 10 | void e_fatal(char* message, char* file, int line); 11 | 12 | #define ASSERT(cond,msg) (cond)?(void)0:e_fatal(msg, __FILE__, __LINE__); 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /src/header/vm-file.h: -------------------------------------------------------------------------------- 1 | #ifndef VM_FILE_H 2 | #define VM_FILE_H 3 | 4 | #include "vproc.h" 5 | 6 | #define VFILE_MAGIC 0x80084545 7 | #define VFILE_INVALID 0xFFFFFFFF 8 | 9 | typedef struct{ 10 | //validation number 11 | var magic; 12 | 13 | //interrupt vectors 14 | var code_start; 15 | var exit_start; 16 | 17 | //load paramaters 18 | var data_size; 19 | var code_size; 20 | var stack_size; 21 | var permissions; 22 | } __attribute__((packed)) vfile_t; 23 | 24 | //loads a process for a particular user 25 | vproc_t* load_vfile(vfile_t* file, var uid, var pid); 26 | 27 | //checks for VM_MAGIC 28 | var validate_vfile(vfile_t* file); 29 | 30 | #endif 31 | -------------------------------------------------------------------------------- /src/header/vsock.h: -------------------------------------------------------------------------------- 1 | #ifndef VSOCK_H 2 | #define VSOCK_H 3 | 4 | //For 'var' datatype 5 | #include "vproc.h" 6 | 7 | //Number of sockets to use 8 | #define VSOCK_SIZE 16 9 | 10 | typedef struct{ 11 | //Required priveledge, smaller is higher priveledge 12 | var priveledge; 13 | //Pid of owner, 0 if public 14 | var pid; 15 | 16 | //If not zero, socket is locked 17 | var locked; 18 | //If not zero, socket is ready to read and return 19 | var ready; 20 | 21 | //Location to write 22 | var input; 23 | //Location to read 24 | var output; 25 | } vsock_t; 26 | 27 | //Table of all vsocks 28 | extern vsock_t** vsock_list; 29 | 30 | //Initialize vsock table 31 | void init_vsocks(); 32 | //Make a socket 33 | var mk_vsock(var priveledge, var pid); 34 | //Remove a socket 35 | var rm_vsock(var sock_id); 36 | 37 | #endif 38 | -------------------------------------------------------------------------------- /src/init.c: -------------------------------------------------------------------------------- 1 | #include "common.h" 2 | #include "init.h" 3 | #include "vfs.h" 4 | #include "deepfat.h" 5 | 6 | void driver_init(){ 7 | //vfs_mkdir(df_root, "/dev"); 8 | DEVLOAD(dev_stdout) 9 | DEVLOAD(dev_stderr) 10 | DEVLOAD(dev_stdin) 11 | DEVLOAD(dev_null) 12 | } 13 | -------------------------------------------------------------------------------- /src/initramfs/as_rd.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | nasm -fbin -oinitrd initrd.asm 4 | -------------------------------------------------------------------------------- /src/initramfs/gen_rd.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | if(ARGV.length < 1) 4 | abort "No files to pack" 5 | end 6 | 7 | puts "Writing header..." 8 | output = "\tdd END - $\n\tdd 0x04206969\n\tdd #{ARGV.length}\n" 9 | 10 | puts "Writing lookup table..." 11 | i = 0 12 | while(i < ARGV.length) 13 | output += "\tdb \"#{ARGV[i]}\",0\n" 14 | output += "\ttimes (128 - #{ARGV[i].length + 1}) db 0\n" 15 | output += "\tdd FILE#{i}\n" 16 | output += "\tdd #{File.size(ARGV[i])}\n" 17 | 18 | i += 1 19 | end 20 | 21 | puts "Writing file paths..." 22 | i = 0 23 | while(i < ARGV.length) 24 | output += "FILE#{i}:\n" 25 | output += "\tincbin \"#{ARGV[i]}\"\n" 26 | 27 | i += 1 28 | end 29 | 30 | puts "Writing footer..." 31 | output += "\tdd 0x04206969\n" 32 | output += "END:" 33 | 34 | puts "Completing write to file..." 35 | file = File.new "initrd.asm", 'w' 36 | file.puts output 37 | file.close 38 | 39 | puts "Success" 40 | -------------------------------------------------------------------------------- /src/initramfs/hello.x: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/16Bitt/virtix/85a3c58f3d3b8932354e85a996a79c377139c201/src/initramfs/hello.x -------------------------------------------------------------------------------- /src/initramfs/makefile: -------------------------------------------------------------------------------- 1 | all: 2 | echo This is a test > text-file.o 3 | ./gen_rd.rb *.o *.x 4 | ./as_rd.sh 5 | rm *.o *.x 6 | rm *.asm 7 | -------------------------------------------------------------------------------- /src/interrupt.s: -------------------------------------------------------------------------------- 1 | [EXTERN istack_base] 2 | [EXTERN stack_hold] 3 | 4 | %macro ISR_BLANK 1 5 | [GLOBAL isr%1] 6 | isr%1: 7 | cli 8 | push byte 0 9 | push byte %1 10 | jmp isr_common_stub 11 | %endmacro 12 | 13 | %macro ISR_ERR 1 14 | [GLOBAL isr%1] 15 | isr%1: 16 | push byte %1 17 | jmp isr_common_stub 18 | %endmacro 19 | 20 | ISR_BLANK 0 21 | ISR_BLANK 1 22 | ISR_BLANK 2 23 | ISR_BLANK 3 24 | ISR_BLANK 4 25 | ISR_BLANK 5 26 | ISR_BLANK 6 27 | ISR_BLANK 7 28 | ISR_ERR 8 29 | ISR_BLANK 9 30 | ISR_ERR 10 31 | ISR_ERR 11 32 | ISR_ERR 12 33 | ISR_ERR 13 34 | ISR_ERR 14 35 | ISR_BLANK 15 36 | ISR_BLANK 16 37 | ISR_BLANK 17 38 | ISR_BLANK 18 39 | ISR_BLANK 19 40 | ISR_BLANK 20 41 | ISR_BLANK 21 42 | ISR_BLANK 22 43 | ISR_BLANK 23 44 | ISR_BLANK 24 45 | ISR_BLANK 25 46 | ISR_BLANK 26 47 | ISR_BLANK 27 48 | ISR_BLANK 28 49 | ISR_BLANK 29 50 | ISR_BLANK 30 51 | ISR_BLANK 31 52 | 53 | ISR_BLANK 32 54 | ISR_BLANK 33 55 | ISR_BLANK 34 56 | ISR_BLANK 35 57 | ISR_BLANK 36 58 | ISR_BLANK 37 59 | ISR_BLANK 38 60 | ISR_BLANK 39 61 | ISR_BLANK 40 62 | ISR_BLANK 41 63 | ISR_BLANK 42 64 | ISR_BLANK 43 65 | ISR_BLANK 44 66 | ISR_BLANK 45 67 | ISR_BLANK 46 68 | ISR_BLANK 47 69 | ISR_BLANK 48 70 | 71 | ISR_BLANK 0x80 72 | 73 | [EXTERN isr_handler] 74 | [EXTERN stack_hold] 75 | 76 | isr_common_stub: 77 | pusha ;REGS 78 | mov ax, ds 79 | push eax ;REGS, EAX 80 | 81 | mov ax, 0x10 82 | mov ds, ax 83 | mov es, ax 84 | mov fs, ax 85 | mov gs, ax 86 | push esp ;REGS, EAX, ESP 87 | 88 | call isr_handler 89 | 90 | add esp, 4 ;REGS, EAX 91 | pop ebx ;REGS 92 | mov ds, bx 93 | mov es, bx 94 | mov fs, bx 95 | mov gs, bx 96 | 97 | popa ;-- 98 | add esp, 8 99 | iret 100 | 101 | %macro IRQ 2 102 | [GLOBAL irq%1] 103 | 104 | irq%1: 105 | ;mov [stack_hold], esp 106 | ;mov esp, [istack_base] 107 | push byte 0 108 | push byte %2 109 | jmp isr_common_stub 110 | %endmacro 111 | 112 | IRQ 0, 32 113 | IRQ 1, 33 114 | IRQ 2, 34 115 | IRQ 3, 35 116 | IRQ 4, 36 117 | IRQ 5, 37 118 | IRQ 6, 38 119 | IRQ 7, 39 120 | IRQ 8, 40 121 | IRQ 9, 41 122 | IRQ 10, 42 123 | IRQ 11, 43 124 | IRQ 12, 44 125 | IRQ 13, 45 126 | IRQ 14, 46 127 | IRQ 15, 47 128 | -------------------------------------------------------------------------------- /src/isr.c: -------------------------------------------------------------------------------- 1 | #include "common.h" 2 | #include "isr.h" 3 | #include "monitor.h" 4 | #include "virtix_page.h" 5 | 6 | isr_t interrupt_handlers[256]; 7 | 8 | unsigned int* istack_base; 9 | 10 | void isr_handler(registers_t* regs){ 11 | /*if(regs->int_no != 0x20){ 12 | vga_puts("CAUGHT INTERRUPT: "); 13 | vga_puts_hex(regs->int_no); 14 | vga_putc('\n'); 15 | }*/ 16 | 17 | if(regs->int_no >= 40) 18 | outb(0xA0, 0x20); 19 | 20 | outb(0x20, 0x20); 21 | 22 | if(interrupt_handlers[regs->int_no]){ 23 | isr_t handler = interrupt_handlers[regs->int_no]; 24 | handler(regs); 25 | } 26 | } 27 | 28 | void register_interrupt_handler(unsigned char index, isr_t handler){ 29 | interrupt_handlers[index] = handler; 30 | } 31 | 32 | void cli(){ 33 | asm volatile ("cli"); 34 | } 35 | 36 | void sti(){ 37 | asm volatile ("sti"); 38 | } 39 | 40 | void hlt(){ 41 | asm volatile ("hlt"); 42 | } 43 | 44 | void ex_gpf(registers_t* regs){ 45 | PANIC("general protection fault"); 46 | } 47 | 48 | void ex_double_fault(registers_t* regs){ 49 | PANIC("double fault"); 50 | } 51 | 52 | void ex_div_by_zero(registers_t* regs){ 53 | PANIC("divide by zero"); 54 | } 55 | 56 | void ex_bad_opcode(registers_t* regs){ 57 | PANIC("bad opcode"); 58 | } 59 | 60 | void ex_bad_tss(registers_t* regs){ 61 | PANIC("bad TSS"); 62 | } 63 | 64 | void ex_bad_simd(registers_t* regs){ 65 | PANIC("fatal simd error"); 66 | } 67 | 68 | void ex_overflow(registers_t* regs){ 69 | vga_puts("\n!OVERFLOW\n"); 70 | } 71 | 72 | void register_default_handlers(){ 73 | register_interrupt_handler(0, ex_div_by_zero); 74 | register_interrupt_handler(4, ex_overflow); 75 | register_interrupt_handler(8, ex_double_fault); 76 | register_interrupt_handler(6, ex_bad_opcode); 77 | register_interrupt_handler(0xA, ex_bad_tss); 78 | register_interrupt_handler(0x13, ex_bad_simd); 79 | register_interrupt_handler(0xD, ex_gpf); 80 | } 81 | -------------------------------------------------------------------------------- /src/keyboard.c: -------------------------------------------------------------------------------- 1 | #include "common.h" 2 | #include "keyboard.h" 3 | #include "isr.h" 4 | #include "monitor.h" 5 | #include "clock.h" 6 | #include "tty.h" 7 | 8 | uchar last_key_pressed = 0; 9 | bool shift_on = FALSE; 10 | int keys_pressed; 11 | 12 | void keyboard_handler(registers_t* regs){ 13 | uchar hold = last_key_pressed; 14 | last_key_pressed = translate_scancode(inb(KEYBOARD_DATA)); 15 | keys_pressed++; 16 | 17 | if(last_key_pressed == 0){ 18 | last_key_pressed = hold; 19 | hold = 0xFF; //This was a dud, ignore 20 | } 21 | 22 | if(hold != 0xFF) //ignore the dud 23 | tty_putc(last_key_pressed); 24 | } 25 | 26 | uint keyboard_getc(){ 27 | uchar hold = last_key_pressed; 28 | last_key_pressed = 0; 29 | return hold; 30 | } 31 | 32 | void init_keyboard(){ 33 | register_interrupt_handler(33, &keyboard_handler); 34 | keys_pressed = 1; 35 | } 36 | 37 | #define BETWEEN(n, l, u) (((n) >= (l)) && ((n) <= (u))) 38 | 39 | char translate_scancode(uchar scancode){ 40 | if(shift_on == FALSE){ 41 | char* qwertyuiop = "qwertyuiop"; 42 | if(BETWEEN(scancode, KBD_Q_DOWN, KBD_P_DOWN)) 43 | return qwertyuiop[scancode - KBD_Q_DOWN]; 44 | 45 | char* asdfghjkl = "asdfghjkl"; 46 | if(BETWEEN(scancode, KBD_A_DOWN, KBD_L_DOWN)) 47 | return asdfghjkl[scancode - KBD_A_DOWN]; 48 | 49 | 50 | char* zxcvbnm = "zxcvbnm"; 51 | if(BETWEEN(scancode, KBD_Z_DOWN, KBD_M_DOWN)) 52 | return zxcvbnm[scancode - KBD_Z_DOWN]; 53 | 54 | char* numbers = "1234567890-=\b"; 55 | if(BETWEEN(scancode, KBD_1_DOWN, KBD_BKSP_DOWN)) 56 | return numbers[scancode - KBD_1_DOWN]; 57 | } 58 | 59 | else{ 60 | char* up_qwertyuiop = "QWERTYUIOP"; 61 | if(BETWEEN(scancode, KBD_Q_DOWN, KBD_P_DOWN)) 62 | return up_qwertyuiop[scancode - KBD_Q_DOWN]; 63 | 64 | char* up_asdfghjkl = "ASDFGHJKL"; 65 | if(BETWEEN(scancode, KBD_A_DOWN, KBD_L_DOWN)) 66 | return up_asdfghjkl[scancode - KBD_A_DOWN]; 67 | 68 | 69 | char* up_zxcvbnm = "ZXCVBNM"; 70 | if(BETWEEN(scancode, KBD_Z_DOWN, KBD_M_DOWN)) 71 | return up_zxcvbnm[scancode - KBD_Z_DOWN]; 72 | 73 | char* up_numbers = "!@#$%^&*()_+\b"; 74 | if(BETWEEN(scancode, KBD_1_DOWN, KBD_BKSP_DOWN)) 75 | return up_numbers[scancode - KBD_1_DOWN]; 76 | } 77 | 78 | switch(scancode){ 79 | case RIGHTSHIFT_DOWN: 80 | case LEFTSHIFT_DOWN: 81 | shift_on = TRUE; 82 | break; 83 | 84 | case RIGHTSHIFT_UP: 85 | case LEFTSHIFT_UP: 86 | shift_on = FALSE; 87 | break; 88 | 89 | case KBD_SPC_DOWN: 90 | return ' '; 91 | 92 | case KBD_ENTER: 93 | return '\n'; 94 | 95 | default: 96 | break; 97 | } 98 | 99 | return 0; 100 | } 101 | -------------------------------------------------------------------------------- /src/kheap.c: -------------------------------------------------------------------------------- 1 | #include "common.h" 2 | #include "kheap.h" 3 | #include "monitor.h" 4 | #include "virtix_page.h" 5 | 6 | unsigned int placement_address; 7 | 8 | heap_header_t* kheap = NULL; 9 | heap_header_t* uheap = NULL; 10 | 11 | void init_kheap(){ 12 | end = (unsigned int) &end; 13 | placement_address = end; 14 | 15 | kheap = (heap_header_t*) fmalloc(KHEAP_SIZE); 16 | init_heap(kheap, KHEAP_SIZE); 17 | 18 | //Make user heap, then map to its 19 | uheap = (heap_header_t*) kmalloc_a(UHEAP_SIZE); 20 | init_heap(uheap, UHEAP_SIZE); 21 | vpage_map_user(root_vpage_dir, (uint) &uheap, (uint) &uheap); 22 | } 23 | 24 | void* fmalloc(unsigned int size){ 25 | //ASSERT(placement_address + size < MEM_END); 26 | unsigned int hold = placement_address; 27 | memset((void*) hold, 0, size); 28 | placement_address += size; 29 | return (void*) hold; 30 | } 31 | 32 | void* kmalloc_a(unsigned int size){ 33 | //ASSERT(((placement_address & 0xFFFFF000) + 0x1000) + size < MEM_END); 34 | placement_address &= 0xFFFFF000; 35 | placement_address += 0x1000; 36 | 37 | unsigned int hold = placement_address; 38 | placement_address += size; 39 | 40 | return (void*) hold; 41 | } 42 | 43 | heap_header_t* find_sized_heap(heap_header_t* heap, size_t size){ 44 | while((heap->size < HEAP_FIND_SIZE + size) || (heap->free != TRUE)){ 45 | ASSERT(heap->magic == KHEAP_MAGIC); 46 | ASSERT(heap->magic2 == KHEAP_MAGIC2); 47 | heap_footer_t* foot = (heap_footer_t*) ((uint) heap + HEAP_S + heap->size); 48 | ASSERT(foot->magic == KHEAP_MAGIC); 49 | ASSERT(foot->magic2 == KHEAP_MAGIC2); 50 | 51 | if(foot->size == KHEAP_END) 52 | PANIC("out of heap space"); 53 | 54 | if(foot->size != heap->size) 55 | PANIC("heap footer/header mismatch"); 56 | 57 | heap = (heap_header_t*) ((uint) foot + sizeof(heap_footer_t)); 58 | } 59 | 60 | return heap; 61 | } 62 | 63 | void split_heap(heap_header_t* heap, size_t size){ 64 | heap_footer_t* foot = (heap_footer_t*) ((uint) heap + HEAP_S + size); 65 | foot->magic = KHEAP_MAGIC; 66 | foot->magic2 = KHEAP_MAGIC2; 67 | foot->size = size; 68 | 69 | size_t new_size = heap->size - HEAP_TOTAL - size; 70 | heap->size = size; 71 | 72 | heap = (heap_header_t*) ((uint) foot + sizeof(heap_footer_t)); 73 | heap->size = new_size; 74 | heap->free = TRUE; 75 | heap->magic = KHEAP_MAGIC; 76 | heap->magic2 = KHEAP_MAGIC2; 77 | 78 | foot = (heap_footer_t*) ((uint) heap + HEAP_S + heap->size); 79 | if((foot->magic != KHEAP_MAGIC) || (foot->magic2 != KHEAP_MAGIC2)){ 80 | WARN("invalid footer in split"); 81 | dump_struct(foot, sizeof(heap_footer_t)); 82 | } 83 | 84 | if(foot->size != KHEAP_END) 85 | foot->size = new_size; 86 | } 87 | 88 | void free_internal(heap_header_t* heap, void* address){ 89 | heap_header_t* head = (heap_header_t*) ((uint) address - HEAP_S); 90 | if(head == heap){ 91 | WARN("can't collapse top of heap"); 92 | head->free = TRUE; 93 | return; 94 | } 95 | 96 | if((head->magic != KHEAP_MAGIC) || (head->magic2 != KHEAP_MAGIC2)){ 97 | //WARN("invalid header in heap"); 98 | //dump_struct(head, sizeof(heap_header_t)); 99 | return; 100 | } 101 | 102 | heap_footer_t* foot = (heap_footer_t*) ((uint) head + HEAP_S + head->size); 103 | if((foot->magic != KHEAP_MAGIC) || (foot->magic2 != KHEAP_MAGIC2)) 104 | PANIC("bad heap in free() call"); 105 | 106 | foot = (heap_footer_t*) ((uint) head - sizeof(heap_footer_t)); 107 | if((foot->magic != KHEAP_MAGIC) || (foot->magic2 != KHEAP_MAGIC2)){ 108 | //WARN("invalid footer in heap"); 109 | return; 110 | } 111 | 112 | if(foot->size == KHEAP_END) 113 | PANIC("impossible condition for heap"); 114 | 115 | heap = (heap_header_t*) ((uint) foot - foot->size - HEAP_S); 116 | if((heap->magic != KHEAP_MAGIC) || (heap->magic2 != KHEAP_MAGIC2)){ 117 | WARN("invalid parent in heap"); 118 | return; 119 | } 120 | 121 | foot = (heap_footer_t*) ((uint) heap + (heap->size + head->size + HEAP_TOTAL) + HEAP_S); 122 | if((foot->magic != KHEAP_MAGIC) || (foot->magic2 != KHEAP_MAGIC2)){ 123 | /*vga_puts("Footer with size of "); 124 | vga_puts_hex(foot->size); 125 | vga_puts(" / head size of "); 126 | vga_puts_hex(heap->size); 127 | vga_puts("\n"); 128 | dump_struct(foot, sizeof(heap_footer_t)); 129 | WARN("fatal arithmetic error in free() call"); 130 | */ 131 | return; 132 | } 133 | 134 | heap->size += head->size + HEAP_TOTAL; 135 | foot->size = heap->size; 136 | } 137 | 138 | void* malloc_internal(heap_header_t* heap, size_t size){ 139 | heap = find_sized_heap(heap, size + 8); 140 | heap->free = FALSE; 141 | split_heap(heap, size); 142 | return (void*) ((uint) heap + HEAP_S); 143 | } 144 | 145 | void init_heap(heap_header_t* heap, size_t size){ 146 | heap->magic = KHEAP_MAGIC; 147 | heap->magic2 = KHEAP_MAGIC2; 148 | heap->free = TRUE; 149 | heap->size = size - HEAP_TOTAL; 150 | 151 | heap_footer_t* foot = (heap_footer_t*) ((uint) heap + HEAP_S + heap->size); 152 | foot->magic = KHEAP_MAGIC; 153 | foot->magic2 = KHEAP_MAGIC2; 154 | foot->size = KHEAP_END; 155 | } 156 | 157 | void* kmalloc(uint size){ 158 | if(kheap == NULL) 159 | return fmalloc(size); 160 | 161 | return malloc_internal(kheap, size); 162 | } 163 | 164 | void kfree(void* address){ 165 | if(kheap == NULL) 166 | return; 167 | 168 | free_internal(kheap, address); 169 | } 170 | 171 | void* umalloc(size_t size){ 172 | return malloc_internal(uheap, size); 173 | } 174 | 175 | void ufree(void* address){ 176 | free_internal(uheap, address); 177 | } 178 | -------------------------------------------------------------------------------- /src/kthread.c: -------------------------------------------------------------------------------- 1 | #include "common.h" 2 | #include "virtix_proc.h" 3 | #include "monitor.h" 4 | #include "isr.h" 5 | #include "virtix_page.h" 6 | #include "kheap.h" 7 | 8 | void mk_kthread(char* name, void* addr){ 9 | cli(); 10 | virtix_proc_t* proc = mk_empty_proc(); 11 | memcpy(&proc->registers, ¤t_proc->registers, sizeof(registers_t)); 12 | sti(); 13 | proc->name = name; 14 | proc->registers.eip = (unsigned int) addr; 15 | proc->registers.useresp = ((unsigned int) kmalloc_a(512)) - 500; 16 | proc->cr3 = root_vpage_dir; 17 | spawn_proc(proc); 18 | } 19 | 20 | void kthread_hlt(){ 21 | vga_puts("kthread halted\n"); 22 | for(;;) 23 | hlt(); 24 | } 25 | 26 | void kthread_exit(){ 27 | unsigned int pid = current_proc->pid; 28 | kill_proc(pid); 29 | kthread_hlt(); 30 | } 31 | -------------------------------------------------------------------------------- /src/link.ld: -------------------------------------------------------------------------------- 1 | /*Linker file for the kernel 2 | Taken from "Bran's Kernel Development"*/ 3 | 4 | ENTRY(start) 5 | SECTIONS 6 | { 7 | /*Executable code*/ 8 | .text 0x1000000 : 9 | { 10 | code = .; _code = .; __code = .; 11 | *(.text) 12 | . = ALIGN(4096); 13 | } 14 | 15 | /*Data and read only data*/ 16 | .data : 17 | { 18 | data = .; _data = .; __data = .; 19 | *(.data) 20 | *(.rodata) 21 | . = ALIGN(4096); 22 | } 23 | 24 | /*Zero initialized data*/ 25 | .bss : 26 | { 27 | bss = .; _bss = .; __bss = .; 28 | *(.bss) 29 | . = ALIGN(4096); 30 | } 31 | 32 | end = .; _end = .; __end = .; 33 | } 34 | -------------------------------------------------------------------------------- /src/makefile: -------------------------------------------------------------------------------- 1 | SOURCES = boot.o $(patsubst %.c,%.o,$(wildcard *.c)) interrupt.o table.o 2 | CFLAGS = -m32 -nostdlib -nostdinc -fno-builtin -fno-stack-protector -Iheader/ -g -Werror 3 | LDFLAGS = -Tlink.ld -melf_i386 4 | ASFLAGS = -felf 5 | CC = i686-elf-gcc 6 | LD = i686-elf-ld 7 | 8 | all: $(SOURCES) link 9 | 10 | clean: 11 | -rm *.o 12 | -rm -rf build/* 13 | 14 | link: 15 | $(LD) $(LDFLAGS) -obuild/kernel $(SOURCES) 16 | 17 | .s.o: 18 | nasm $(ASFLAGS) $< 19 | 20 | binaries: 21 | cd userlaand && make 22 | -------------------------------------------------------------------------------- /src/monitor.c: -------------------------------------------------------------------------------- 1 | #include "monitor.h" 2 | #include "isr.h" 3 | #include "stdarg.h" 4 | 5 | int cursor_x = 0, cursor_y = 0; 6 | uchar vga_color; 7 | 8 | unsigned short* vga_buffer = ((unsigned short*) 0xB8000); 9 | 10 | void update_cursor(){ 11 | unsigned short location = cursor_y * 80 + cursor_x; 12 | outb(0x3D4, 14); 13 | outb(0x3D5, location >> 8); 14 | outb(0x3D4, 15); 15 | outb(0x3D5, location); 16 | } 17 | 18 | static void scroll(){ 19 | unsigned char attribute = 15; 20 | unsigned short empty = 0x20 | (attribute << 8); 21 | 22 | if(cursor_y >= 25){ 23 | int i; 24 | for(i = 0; i < 25 * 80; i++) 25 | vga_buffer[i] = vga_buffer[i + 80]; 26 | 27 | for(i = 24 * 80; i < 25 * 80; i++) 28 | vga_buffer[i] = vga_buffer[i + 80]; 29 | 30 | cursor_y = 24; 31 | } 32 | } 33 | 34 | void vga_putc(char c){ 35 | unsigned short attribute = vga_color << 8; 36 | unsigned short* location; 37 | 38 | if(c == 0x08 && cursor_x) 39 | cursor_x--; 40 | else if(c == 0x09) 41 | cursor_x = (cursor_x + 8) & ~(8 - 1); 42 | else if(c == '\r') 43 | cursor_x = 0; 44 | else if(c == '\n'){ 45 | cursor_x = 0; 46 | cursor_y++; 47 | } 48 | else if(c >= ' '){ 49 | location = vga_buffer + (cursor_y * 80 + cursor_x); 50 | *location = c | attribute; 51 | cursor_x++; 52 | } 53 | 54 | if(cursor_x >= 80){ 55 | cursor_x = 0; 56 | cursor_y++; 57 | } 58 | 59 | scroll(); 60 | update_cursor(); 61 | } 62 | 63 | void vga_puts(char* s){ 64 | int i = 0; 65 | 66 | while(s[i]) 67 | vga_putc(s[i++]); 68 | } 69 | 70 | void vga_puts_hex(int n){ 71 | char* reference = "0123456789ABCDEF"; 72 | 73 | vga_puts("0x"); 74 | 75 | int i; 76 | for(i = 28; i > -1; i -= 4) 77 | vga_putc(reference[(n >> i) & 0xF]); 78 | } 79 | 80 | void vga_putc_hex(char n){ 81 | char* reference = "0123456789ABCDEF"; 82 | 83 | int i; 84 | for(i = 4; i > -1; i -= 4) 85 | vga_putc(reference[(n >> i) & 0xF]); 86 | } 87 | 88 | void vga_clear(){ 89 | unsigned short empty = 0x20 | (15 << 8); 90 | 91 | int i; 92 | for(i = 0; i < 80 * 25; i++) 93 | vga_buffer[i] = empty; 94 | 95 | cursor_x = cursor_y = 0; 96 | update_cursor(); 97 | } 98 | 99 | void vga_set_fg(uchar color){ 100 | vga_color &= 0xF0; 101 | vga_color |= color; 102 | } 103 | 104 | void vga_set_bg(uchar color){ 105 | vga_color &= 0xF; 106 | vga_color |= (color << 4); 107 | } 108 | 109 | void vga_blink(){ 110 | vga_color |= 0x80; 111 | } 112 | 113 | void vga_reset(){ 114 | vga_set_fg(WHITE); 115 | vga_set_bg(BLACK); 116 | } 117 | 118 | void vga_puts_dec(int n){ 119 | if(n == 0){ 120 | vga_putc('0'); 121 | return; 122 | } 123 | 124 | if(n < 0){ 125 | vga_putc('-'); 126 | n *= -1; 127 | } 128 | 129 | char output[20]; 130 | 131 | int end = 0; 132 | while(n != 0){ 133 | char digit = n % 10; 134 | output[end++] = '0' + digit; 135 | n /= 10; 136 | } 137 | 138 | while(end > 0) 139 | vga_putc(output[--end]); 140 | } 141 | 142 | void vga_fmt(const char* fmt, ...){ 143 | va_list params; 144 | va_start(params, fmt); 145 | 146 | int arg = 0; 147 | while(*fmt != '\0'){ 148 | if(*fmt == '%'){ 149 | char op = *(++fmt); 150 | switch(op){ 151 | case 'd': 152 | case 'i': 153 | vga_puts_dec(va_arg(params, int)); 154 | break; 155 | case 'x': 156 | case 'X': 157 | vga_puts_hex(va_arg(params, uint)); 158 | break; 159 | case 's': 160 | vga_puts(va_arg(params, char*)); 161 | break; 162 | 163 | default: 164 | WARN("bad specifier"); 165 | return; 166 | } 167 | } 168 | 169 | else 170 | vga_putc(*fmt); 171 | 172 | fmt++; 173 | } 174 | } 175 | -------------------------------------------------------------------------------- /src/paging.c: -------------------------------------------------------------------------------- 1 | #include "common.h" 2 | #include "monitor.h" 3 | #include "paging.h" 4 | #include "isr.h" 5 | #include "virtix_proc.h" 6 | #include "kheap.h" 7 | #include "virtix_page.h" 8 | 9 | unsigned int* current_dir = 0; 10 | unsigned int* process_dir = 0; 11 | 12 | unsigned int* root_dir = 0; 13 | 14 | static unsigned int page_dir_location = 0; 15 | static unsigned int* last_page = 0; 16 | 17 | static unsigned int proc_dir = 0; 18 | /* 19 | void map_vpage_to_ppage(unsigned int virtual, unsigned int physical){ 20 | short id = virtual >> 22; 21 | 22 | int i; 23 | for(i = 0; i < 1024; i++){ 24 | last_page[i] = physical | 3; 25 | physical += 4096; 26 | } 27 | 28 | current_dir[id] = ((unsigned int) last_page) | 3; 29 | last_page = (unsigned int*) (((unsigned int) last_page) + 4096); 30 | } 31 | 32 | void enable_paging(){ 33 | //page_dir_location = (unsigned int) ¤t_dir[0]; 34 | asm volatile ("mov %%eax, %%cr3" :: "a" (page_dir_location)); 35 | asm volatile ("mov %cr0, %eax"); 36 | asm volatile ("orl $0x80000000, %eax"); 37 | asm volatile ("mov %eax, %cr0"); 38 | } 39 | 40 | void switch_page(unsigned int* page_dir){ 41 | current_dir = page_dir; 42 | 43 | if(page_dir != root_dir){ 44 | dump_page(page_dir); 45 | dump_page((unsigned int*) ((unsigned int) ((*((unsigned int*) page_dir))) & 0xFFFFF000)); 46 | //cli(); 47 | //hlt(); 48 | } 49 | 50 | asm volatile("mov %0, %%cr3":: "r"(&page_dir[0])); 51 | u32int cr0; 52 | asm volatile("mov %%cr0, %0": "=r"(cr0)); 53 | cr0 |= 0x80000000; 54 | asm volatile("mov %0, %%cr0":: "r"(cr0)); 55 | } 56 | 57 | void init_paging(){ 58 | current_dir = (unsigned int*) PAGE_S; 59 | page_dir_location = (unsigned int) current_dir; 60 | last_page = (unsigned int*) (PAGE_S + 4096); 61 | //last_page = ((unsigned int) current_dir) + PAGE_S; 62 | root_dir = current_dir; 63 | 64 | unsigned int i; 65 | for(i = 0; i < 1024; i++) 66 | current_dir[i] = 0 | 2; 67 | 68 | for(i = 0; i < 0x8000000; i += PAGE_S) 69 | map_vpage_to_ppage(i, i); //Identity mapping the entire kernel 70 | 71 | register_interrupt_handler(14, page_fault); 72 | cli(); 73 | 74 | switch_page(root_dir); 75 | } 76 | 77 | void page_fault(registers_t* regs){ 78 | cli(); 79 | if(current_proc != NULL){ 80 | dump_proc(current_proc); 81 | } 82 | 83 | unsigned int err_pos; 84 | asm volatile ("mov %%cr2, %0" : "=r" (err_pos)); 85 | 86 | vga_puts("Page fault occurred at "); 87 | vga_puts_hex(err_pos); 88 | 89 | vga_puts("\nReasons:"); 90 | 91 | int no_page = regs->err_code & 1; 92 | int rw = regs->err_code & 2; 93 | int um = regs->err_code & 4; 94 | int re = regs->err_code & 8; 95 | int dc = regs->err_code & 16; 96 | 97 | if(dc) vga_puts(" (Instruction decode error) "); 98 | if(!no_page) vga_puts(" (No page present) "); 99 | if(um) vga_puts(" (in user mode) "); 100 | if(rw) vga_puts(" (Write permissions) "); 101 | if(re) vga_puts(" (RE) "); 102 | 103 | 104 | PANIC("PAGE FAULT"); 105 | } 106 | 107 | void mmap_page(unsigned int* page_dir, unsigned int vpage, unsigned int ppage){ 108 | vga_puts("mmap(): "); vga_puts_hex(ppage); vga_puts(" to "); vga_puts_hex(vpage); 109 | vga_puts("\n"); 110 | 111 | short id = vpage >> 22; 112 | 113 | unsigned int* page = mk_page(); //CONFIRMED 114 | 115 | int i; 116 | for(i = 0; i < 1024; i++){ 117 | page[i] = ppage | 2 | 1; //User mode, RW, present 118 | ppage += 4096; 119 | } 120 | 121 | page_dir[id] = ((unsigned int) page) | 3; //User mode, RW, present 122 | } 123 | 124 | unsigned int* mk_page(){ //WORKS 125 | unsigned int* page = (unsigned int*) kmalloc_a(4096); 126 | int i; 127 | for(i = 0; i < 1024; i++) 128 | page[i] = 2; 129 | return page; 130 | } 131 | 132 | unsigned int* mk_page_dir(){ //WORKS 133 | unsigned int* dir = (unsigned int*) kmalloc_a(4096); 134 | 135 | int i; 136 | for(i = 0; i < 1024; i++){ 137 | dir[i] = 2; 138 | } 139 | 140 | return (unsigned int*) dir; 141 | } 142 | 143 | void dump_page(unsigned int* dir){ 144 | vga_puts("Dumping page at "); 145 | vga_puts_hex(dir); 146 | vga_puts(":\n"); 147 | 148 | int i; 149 | for(i = 0; i < 4; i++){ 150 | vga_puts_hex(dir[i]); 151 | vga_puts(" "); 152 | } 153 | 154 | vga_puts("\n"); 155 | } 156 | */ 157 | -------------------------------------------------------------------------------- /src/real.c: -------------------------------------------------------------------------------- 1 | #include "common.h" 2 | #include "real.h" 3 | #include "monitor.h" 4 | #include "clock.h" 5 | #include "file.h" 6 | #include "kheap.h" 7 | 8 | void run_stub16(char* file){ 9 | FILE f = kfopen(file, 0); 10 | struct stat* st = (struct stat*) kmalloc(sizeof(struct stat)); 11 | kfstat(f, st); 12 | if(st->st_size == 0){ 13 | kfclose(f); 14 | WARN("16-bit stub load failed: empty file"); 15 | return; 16 | } 17 | 18 | kfread(f, st->st_size, (char*) 0x7C00); 19 | 20 | WARN("Entering real mode in 3 seconds"); 21 | sleep(3); 22 | WARN("cross your fingers") 23 | asm volatile ("jmp 0x7C00"); 24 | } 25 | -------------------------------------------------------------------------------- /src/signal.c: -------------------------------------------------------------------------------- 1 | #include "common.h" 2 | #include "isr.h" 3 | #include "monitor.h" 4 | #include "signal.h" 5 | #include "virtix_proc.h" 6 | 7 | void raise(virtix_proc_t* proc, uint signal){ 8 | PANIC("No signal handling per process"); 9 | } 10 | 11 | void signal(virtix_proc_t* proc, uint signal, uint func){ 12 | WARN("does not support signals... Yet") 13 | } 14 | -------------------------------------------------------------------------------- /src/single.c: -------------------------------------------------------------------------------- 1 | #include "common.h" 2 | #include "monitor.h" 3 | #include "virtix_proc.h" 4 | #include "isr.h" 5 | #include "file.h" 6 | 7 | virtix_proc_t* proc_bottom = NULL; 8 | 9 | //These values are read by hardload function 10 | unsigned int hl_cr3; 11 | unsigned int hl_eip; 12 | unsigned int hl_esp; 13 | 14 | unsigned int sp_child(){ 15 | return (unsigned int) -1; 16 | } 17 | 18 | extern void hard_usermode(); 19 | 20 | void enter_userspace(virtix_proc_t* proc){ 21 | proc_bottom = proc; 22 | proc->next = NULL; 23 | hl_eip = proc->registers.eip; 24 | hl_esp = proc->registers.esp; 25 | switch_vpage_dir(proc->cr3); 26 | 27 | current_proc = proc; 28 | 29 | sti(); 30 | hard_usermode(); 31 | } 32 | 33 | void single_yield(virtix_proc_t* proc, registers_t* regs){ 34 | memcpy(&proc_bottom->registers, regs, sizeof(registers_t)); 35 | 36 | if(proc == proc_bottom) 37 | PANIC("Can't return from parent process"); 38 | 39 | proc->next = proc_bottom; 40 | proc_bottom = proc; 41 | 42 | memcpy(regs, &proc->registers, sizeof(registers_t)); 43 | switch_vpage_dir(proc->cr3); 44 | } 45 | 46 | unsigned int single_exit(registers_t* regs){ 47 | kfclose(current_proc->stdout); 48 | kfclose(current_proc->stderr); 49 | 50 | unsigned int hold = regs->ebx; 51 | proc_bottom = proc_bottom->next; 52 | 53 | if(proc_bottom == NULL) 54 | PANIC("return from process with no parent"); 55 | 56 | memcpy(regs, &proc_bottom->registers, sizeof(registers_t)); 57 | switch_vpage_dir(proc_bottom->cr3); 58 | 59 | return hold; 60 | } 61 | -------------------------------------------------------------------------------- /src/str-util.c: -------------------------------------------------------------------------------- 1 | #include "common.h" 2 | #include "str-util.h" 3 | 4 | char* prep_str(char* str){ 5 | int i = 0; 6 | while(str[i] != 0){ 7 | if((str[i] == ' ') || (str[i] == '\n')) 8 | str[i] = 0; 9 | i++; 10 | } 11 | 12 | return str; 13 | } 14 | 15 | char* next_str(char* str){ 16 | str = &str[strlen(str)]; 17 | 18 | int i = 0; 19 | while(str[i] == 0) 20 | i++; 21 | 22 | return &str[i]; 23 | } 24 | 25 | void strmov(char* dest, char* src){ 26 | int i; 27 | for(i = 0; i <= strlen(src); i++) 28 | dest[i] = src[i]; 29 | } 30 | -------------------------------------------------------------------------------- /src/table.s: -------------------------------------------------------------------------------- 1 | [BITS 32] 2 | [GLOBAL idt_flush] 3 | 4 | idt_flush: 5 | mov eax, [esp + 4] 6 | lidt [eax] 7 | ret 8 | 9 | [GLOBAL gdt_flush] 10 | 11 | gdt_flush: 12 | mov eax, [esp + 4] 13 | lgdt [eax] 14 | 15 | mov ax, 0x10 16 | mov ds, ax 17 | mov es, ax 18 | mov fs, ax 19 | mov gs, ax 20 | mov ss, ax 21 | jmp 0x08:.flush 22 | .flush: 23 | ret 24 | -------------------------------------------------------------------------------- /src/tty.c: -------------------------------------------------------------------------------- 1 | #include "common.h" 2 | #include "monitor.h" 3 | #include "tty.h" 4 | #include "isr.h" 5 | 6 | extern void scroll(); 7 | extern void update_cursor(); 8 | extern int cursor_x, cursor_y; 9 | 10 | uchar tty_fg = WHITE; 11 | uchar tty_bg = BLACK; 12 | short tty_row; 13 | short tty_col; 14 | 15 | bool tty_echo = true; 16 | bool tty_esc_mode = false; 17 | 18 | char tty_key = 0; 19 | 20 | char esc_buf[256]; 21 | int esc_index = 0; 22 | 23 | int tty_parse_int(char* s){ 24 | int x = 0; 25 | while((*s != '\0') && (*s != ';') && (*s != 'm')){ 26 | if((*s >= '0') && (*s <= '9')){ 27 | x *= 10; 28 | x += *s - '0'; 29 | } 30 | s++; 31 | } 32 | 33 | return x; 34 | } 35 | 36 | int tty_ansi_to_vga(int color, int mode){ 37 | if(mode) 38 | switch(color){ 39 | case 30: 40 | 41 | case 34: 42 | return LIGHT_BLUE; 43 | case 32: 44 | return LIGHT_GREEN; 45 | case 36: 46 | return LIGHT_CYAN; 47 | case 31: 48 | return LIGHT_RED; 49 | case 35: 50 | return LIGHT_MAGENTA; 51 | case 33: 52 | return LIGHT_BROWN; 53 | case 37: 54 | return WHITE; 55 | default: 56 | return WHITE; 57 | } 58 | 59 | else 60 | switch(color){ 61 | case 30: 62 | return BLACK; 63 | case 34: 64 | return BLUE; 65 | case 32: 66 | return GREEN; 67 | case 36: 68 | return CYAN; 69 | case 31: 70 | return RED; 71 | case 35: 72 | return MAGENTA; 73 | case 33: 74 | return BROWN; 75 | case 37: 76 | return LIGHT_GREY; 77 | default: 78 | return WHITE; 79 | } 80 | } 81 | 82 | void tty_parse_escape(){ 83 | int i = 0; 84 | if(esc_buf[i] == '['){ 85 | i++; 86 | } 87 | 88 | int command = tty_parse_int(&esc_buf[i]); 89 | int args[20]; //Possible security problem... 90 | memset(args, 0, sizeof(args)); 91 | int arg = 0; 92 | 93 | while(esc_buf[i] != '\0'){ 94 | while(esc_buf[i] != ';'){ 95 | if(esc_buf[i] == '\0') 96 | break; 97 | i++; 98 | } 99 | i++; 100 | 101 | args[arg++] = tty_parse_int(&esc_buf[i]); 102 | } 103 | 104 | switch(command){ 105 | case 0: //Basic colors 106 | tty_fg = tty_ansi_to_vga(args[0], 0); 107 | break; 108 | case 1: //Other colors 109 | tty_fg = tty_ansi_to_vga(args[0], 1); 110 | break; 111 | 112 | default: 113 | WARN("Unknown vt220 mode"); 114 | } 115 | } 116 | 117 | void add_to_escape(char c){ 118 | if(c == 'm'){ 119 | esc_index = 0; 120 | tty_parse_escape(); 121 | memset(esc_buf, 0, sizeof(esc_buf)); 122 | tty_esc_mode = false; 123 | return; 124 | } 125 | 126 | esc_buf[esc_index++] = c; 127 | if(esc_index >= 255) 128 | esc_index = 0; 129 | } 130 | 131 | void tty_clear(){ 132 | vga_clear(); 133 | tty_row = 0; 134 | tty_col = 0; 135 | } 136 | 137 | void tty_reset(){ 138 | tty_clear(); 139 | tty_bg = BLACK; 140 | tty_fg = WHITE; 141 | tty_echo = true; 142 | } 143 | 144 | void tty_backspace(){ 145 | if(cursor_x == 0){ 146 | if(cursor_y > 0){ 147 | cursor_y--; 148 | cursor_x = TTY_WIDTH - 1; 149 | update_cursor(); 150 | } 151 | } 152 | 153 | else{ 154 | cursor_x--; 155 | vga_putc(' '); 156 | cursor_x--; 157 | update_cursor(); 158 | } 159 | } 160 | 161 | void tty_putc(char c){ 162 | switch(c){ 163 | case 27: //Escape 164 | tty_esc_mode = true; 165 | break; 166 | case '\b': //Backspace 167 | tty_backspace(); 168 | break; 169 | default: 170 | if(tty_esc_mode) 171 | add_to_escape(c); 172 | else if(tty_echo){ 173 | vga_set_fg(tty_fg); 174 | vga_set_bg(tty_bg); 175 | vga_putc(c); 176 | } 177 | } 178 | } 179 | -------------------------------------------------------------------------------- /src/userspace.c: -------------------------------------------------------------------------------- 1 | #include "common.h" 2 | #include "monitor.h" 3 | #include "isr.h" 4 | #include "virtix_proc.h" 5 | #include "userspace.h" 6 | #include "single.h" 7 | #include "kheap.h" 8 | #include "file.h" 9 | #include "exec.h" 10 | #include "signal.h" 11 | #include "fat.h" 12 | 13 | uint c_err; 14 | 15 | void userspace_handler(registers_t* regs){ 16 | switch(regs->eax){ 17 | //One liners 18 | case SYS_FORK: 19 | regs->eax = fork(regs); 20 | return; 21 | case SYS_GETPID: 22 | regs->eax = getpid(); 23 | return; 24 | case SYS_GETENV: 25 | regs->eax = (uint) get_env(); 26 | return; 27 | case SYS_GETSTDIN: 28 | regs->eax = current_proc->stdin; 29 | return; 30 | case SYS_GETSTDOUT: 31 | regs->eax = current_proc->stdout; 32 | return; 33 | case SYS_GETSTDERR: 34 | regs->eax = current_proc->stderr; 35 | return; 36 | case SYS_GETGID: 37 | regs->eax = current_proc->gid; 38 | return; 39 | case SYS_SYNC: 40 | fat_sync(); 41 | regs->eax = 0; 42 | return; 43 | 44 | //Need arguments 45 | case SYS_WRITE: 46 | regs->eax = write(regs->ebx, (char*) regs->ecx, (size_t) regs->edx); 47 | return; 48 | case SYS_READ: 49 | regs->eax = read(regs->ebx, (char*) regs->ecx, (size_t) regs->edx); 50 | return; 51 | case SYS_CLOSE: 52 | regs->eax = close(regs->ebx); 53 | return; 54 | case SYS_LSEEK: 55 | regs->eax = klseek(regs->ebx, regs->ecx, regs->edx); 56 | return; 57 | case SYS_OPEN: 58 | regs->eax = open((char*) regs->ebx, regs->ecx); 59 | return; 60 | case SYS_FSTAT: 61 | regs->eax = kfstat((uint) regs->ebx, (struct stat*) regs->ecx); 62 | return; 63 | case SYS_STAT: 64 | regs->eax = kstat((char*) regs->ebx, (struct stat*) regs->ecx); 65 | return; 66 | case SYS_EXEC: 67 | if(uexec((char*) regs->ebx) != 0) 68 | regs->eax = (uint) -1; 69 | scheduler(regs); 70 | return; 71 | case SYS_SBRK: 72 | WARN("very bad sbrk implementation"); 73 | uint ptr = (uint) kmalloc_a(PAGE_S); 74 | vpage_map_user(current_proc->cr3, current_proc->brk, ptr); 75 | regs->eax = current_proc->brk; 76 | current_proc->brk += PAGE_S; 77 | return; 78 | case SYS_MALLOC: 79 | regs->eax = (uint) umalloc(regs->ebx); 80 | return; 81 | case SYS_FREE: 82 | ufree((void*) regs->ebx); 83 | return; 84 | case SYS_RAISE: 85 | raise(current_proc, regs->ebx); 86 | return; 87 | case SYS_SIGNAL: 88 | signal(current_proc, regs->ebx, regs->ecx); 89 | return; 90 | case SYS_WAIT: 91 | regs->eax = sys_wait((int) regs->ebx, (int*) regs->ecx, regs->edx); 92 | return; 93 | 94 | //Modifies the process 95 | case SYS_EXIT: 96 | regs->eax = _exit(regs); //leave return code for parent 97 | scheduler(regs); 98 | return; 99 | 100 | default: 101 | memcpy(¤t_proc->registers, regs, sizeof(registers_t)); 102 | dump_proc(current_proc); 103 | PANIC("bad userspace call"); 104 | } 105 | } 106 | 107 | int sys_wait(int pid, int* status, int options){ 108 | int ret; 109 | 110 | if(pid < 0){ //Wait for any process in |gid| to die 111 | ret = wait_gid(pid * -1, status); 112 | } 113 | 114 | if(pid == -1){ //Wait for any child to be killed 115 | ret = wait_gid(current_proc->pid, status); 116 | } 117 | 118 | if(pid == 0){ //Wait for siblings of this process to die 119 | ret = wait_gid(current_proc->gid, status); 120 | } 121 | 122 | if(pid > 0){ //Wait for pid to die 123 | ret = wait_pid(pid, status); 124 | } 125 | 126 | return ret; 127 | } 128 | 129 | void init_userspace(){ 130 | register_interrupt_handler(31, userspace_handler); 131 | } 132 | 133 | uint fork(registers_t* regs){ 134 | vpage_dir_t* dir = copy_user_dir(current_proc->cr3); 135 | virtix_proc_t* proc = mk_empty_proc(); 136 | proc->cr3 = dir; 137 | memcpy(&proc->registers, regs, sizeof(registers_t)); 138 | proc->registers.eax = proc->pid; 139 | proc->pid = current_proc->pid; 140 | 141 | spawn_proc(proc); 142 | 143 | return 0; 144 | } 145 | 146 | uint getpid(){ 147 | return current_proc->pid; 148 | } 149 | 150 | char** get_env(){ 151 | return (char**) NULL; 152 | } 153 | 154 | FILE open(char* path, uint offset){ 155 | return kfopen(path, offset); 156 | } 157 | 158 | uint close(FILE fid){ 159 | kfclose(fid); 160 | return 0; 161 | } 162 | 163 | uint read(FILE fid, char* buffer, size_t length){ 164 | return kfread(fid, length, buffer); 165 | } 166 | 167 | uint write(FILE fid, char* buffer, size_t length){ 168 | return kfwrite(fid, length, buffer); 169 | } 170 | 171 | uint _exit(registers_t* regs){ 172 | current_proc->state = PROC_ASLEEP; 173 | return regs->eax; 174 | } 175 | -------------------------------------------------------------------------------- /src/vfs.c: -------------------------------------------------------------------------------- 1 | #include "common.h" 2 | #include "monitor.h" 3 | #include "kheap.h" 4 | #include "vfs.h" 5 | #include "str-util.h" 6 | #include "deepfat.h" 7 | 8 | uint read_fs(fs_node_t* node, uint offset, uchar* buffer){ 9 | if(node->read_blk != NULL) 10 | return node->read_blk(node, offset, buffer); 11 | else 12 | return 0; 13 | } 14 | 15 | uint write_fs(fs_node_t* node, uint offset, uchar* buffer){ 16 | if(node->write_blk != NULL) 17 | return node->write_blk(node, offset, buffer); 18 | else 19 | return 0; 20 | } 21 | 22 | uint open_fs(fs_node_t* node, uint offset){ 23 | if(node->open != NULL) 24 | return node->open(node, offset); 25 | } 26 | 27 | void close_fs(fs_node_t* node){ 28 | if(node->close != NULL) 29 | node->close(node); 30 | } 31 | 32 | struct dirent* readdir_fs(fs_node_t* node, uint index){ 33 | if((node->readdir != NULL) && ((node->flags & 7) == FS_DIRECTORY)) 34 | return node->readdir(node, index); 35 | else 36 | return (struct dirent*) NULL; 37 | } 38 | 39 | fs_node_t* finddir_fs(fs_node_t* node, char* name){ 40 | if((node->readdir != NULL) && ((node->flags & 7) == FS_DIRECTORY)) 41 | return node->finddir(node, name); 42 | else 43 | return (fs_node_t*) NULL; 44 | } 45 | 46 | fs_node_t* fs_path(fs_node_t* node, char* name){ 47 | //Copy the name for when we modify it 48 | if(strcmp(name, "/") == 0) 49 | return node; 50 | 51 | char* cpy = (char*) kmalloc(strlen(name) + 2); 52 | strmov(cpy, name); 53 | cpy[strlen(name) + 1] = 1; //Any non-zero character works, solely for next_str 54 | 55 | name = cpy; 56 | char* end = &name[strlen(name)]; 57 | 58 | //Format for parsing (zero-style parsing) 59 | int i, len = strlen(name); 60 | for(i = 0; i < len; i++) 61 | if(name[i] == '/') 62 | name[i] = 0; 63 | 64 | if(strlen(name) == 0) 65 | name = next_str(name); 66 | 67 | //Iterate down the pathname 68 | do{ 69 | node = node->holds; 70 | 71 | while(node != NULL){ 72 | if(strcmp(node->name, name) == 0) 73 | break; 74 | 75 | node = node->link; 76 | } 77 | 78 | if(node == NULL){ 79 | return NULL; 80 | } 81 | 82 | name = next_str(name); 83 | }while((uint) name < (uint) end); 84 | 85 | kfree(cpy); 86 | return node; 87 | } 88 | 89 | struct dirent* readdir_generic(fs_node_t* node, uint index){ 90 | fs_node_t* link = node->holds; 91 | 92 | while(index != 0){ 93 | if(link == NULL) 94 | return NULL; 95 | 96 | link = link->link; 97 | index--; 98 | } 99 | 100 | if(link == NULL) 101 | return NULL; 102 | 103 | struct dirent* dir = (struct dirent*) kmalloc(sizeof(struct dirent)); 104 | strmov(dir->name, link->name); 105 | dir->ino = link->inode; 106 | return dir; 107 | } 108 | 109 | void vfs_ls(char* path){ 110 | fs_node_t* dir = fs_path(df_root, path); 111 | if(dir == NULL){ 112 | vga_puts("vfs_ls(): invalid path\n"); 113 | return; 114 | } 115 | 116 | fs_node_t* link = dir->holds; 117 | 118 | vga_puts("directory listing for "); 119 | vga_puts(path); 120 | vga_puts("\n"); 121 | while(link != NULL){ 122 | vga_puts(link->name); 123 | if(link->flags == FS_DIRECTORY) 124 | vga_puts("/"); 125 | vga_puts("\n"); 126 | link = link->link; 127 | } 128 | } 129 | 130 | fs_node_t* vfs_get_dir(fs_node_t* node, char* name){ 131 | char* cpy = (char*) kmalloc(strlen(name) + 2); 132 | char* ref = cpy; 133 | strmov(cpy, name); 134 | cpy[strlen(name) + 1] = 1; //Any nonzero value works here 135 | name = cpy; 136 | 137 | int i; 138 | for(i = strlen(name); i >= 0; i--) 139 | if(name[i] == '/'){ 140 | name[i] = 0; 141 | break; 142 | } 143 | 144 | fs_node_t* output; 145 | if(strlen(name) == 0) 146 | output = df_root; 147 | else 148 | output = fs_path(node, name); 149 | 150 | kfree(ref); 151 | return output; 152 | } 153 | 154 | char* basename(char* name){ 155 | int i; 156 | for(i = strlen(name); i >= 0; i--) 157 | if(name[i] == '/') 158 | return &name[i + 1]; 159 | 160 | return name; 161 | } 162 | 163 | fs_node_t* vfs_touch(fs_node_t* node, char* name){ 164 | fs_node_t* dir = vfs_get_dir(node, name); 165 | 166 | if(dir == NULL) 167 | return NULL; 168 | 169 | fs_node_t* file = mk_empty_fnode(); 170 | strmov(file->name, basename(name)); 171 | 172 | fat_dir_t* entry = df_new_file(); 173 | 174 | if(entry == NULL) 175 | PANIC("kernel attempted to overwrite file in FAT"); 176 | 177 | int i; 178 | for(i = 0; i < 11; i++){ 179 | file->dos_name[i] = entry->name[i]; 180 | } 181 | 182 | file->link = dir->holds; 183 | dir->holds = file; 184 | 185 | return file; 186 | } 187 | 188 | fs_node_t* vfs_mkdir(fs_node_t* node, char* name){ 189 | fs_node_t* dir = vfs_get_dir(node, name); 190 | if(dir == NULL){ 191 | vga_puts("vfs_mkdir(): invalid path\n"); 192 | return NULL; 193 | } 194 | 195 | fs_node_t* file = mk_empty_dnode(); 196 | strmov(file->name, basename(name)); 197 | 198 | file->link = dir->holds; 199 | dir->holds = file; 200 | 201 | return file; 202 | } 203 | -------------------------------------------------------------------------------- /src/virtix_page.c: -------------------------------------------------------------------------------- 1 | #include "common.h" 2 | #include "monitor.h" 3 | #include "virtix_page.h" 4 | #include "kheap.h" 5 | #include "virtix_proc.h" 6 | 7 | vpage_dir_t* current_vpage_dir = NULL; 8 | vpage_dir_t* root_vpage_dir = NULL; 9 | 10 | //Assembly abstraction for more maintainable code 11 | page_table_t* get_cr3(){ 12 | unsigned int cr3; 13 | 14 | asm volatile ("movl %%cr3, %%eax" : "=a" (cr3)); 15 | return (page_table_t*) cr3; 16 | } 17 | 18 | unsigned int get_cr0(){ 19 | unsigned int cr0; 20 | 21 | asm volatile ("movl %%cr0, %%eax" : "=a" (cr0)); 22 | return cr0; 23 | } 24 | 25 | void set_cr3(vpage_dir_t* dir){ 26 | unsigned int addr = (unsigned int) &dir->tables[0]; 27 | asm volatile ("movl %%eax, %%cr3" :: "a" (addr)); 28 | } 29 | 30 | inline void set_cr0(unsigned int new_cr0){ 31 | asm volatile ("movl %%eax, %%cr0" :: "a" (new_cr0)); 32 | } 33 | 34 | void switch_vpage_dir(vpage_dir_t* dir){ 35 | set_cr3(dir); 36 | set_cr0(get_cr0() | 0x80000000); 37 | } 38 | 39 | //Utility code for paging 40 | vpage_dir_t* mk_vpage_dir(){ 41 | vpage_dir_t* dir = (vpage_dir_t*) kmalloc_a(sizeof(vpage_dir_t)); 42 | 43 | int i; 44 | for(i = 0; i < 1024; i++) 45 | dir->tables[i] = EMPTY_TAB; 46 | 47 | return dir; 48 | } 49 | 50 | page_table_t* mk_vpage_table(){ 51 | page_table_t* tab = (page_table_t*) kmalloc_a(sizeof(page_table_t)); 52 | 53 | int i; 54 | for(i = 0; i < 1024; i++){ 55 | tab->pages[i].present = 0; 56 | tab->pages[i].rw = 1; 57 | } 58 | 59 | return tab; 60 | } 61 | 62 | void vpage_map(vpage_dir_t* dir, unsigned int phys, unsigned int virt){ 63 | short id = virt >> 22; 64 | page_table_t* tab = mk_vpage_table(); 65 | 66 | dir->tables[id] = ((page_table_t*)((unsigned int) tab | 3)); //Writeable/present 67 | 68 | int i; 69 | for(i = 0; i < 1024; i++){ 70 | tab->pages[i].frame = phys >> 12; 71 | tab->pages[i].present = 1; 72 | phys += 4096; 73 | } 74 | } 75 | 76 | void vpage_map_user(vpage_dir_t* dir, unsigned int phys, unsigned int virt){ 77 | short id = virt >> 22; 78 | page_table_t* tab = mk_vpage_table(); 79 | 80 | dir->tables[id] = ((page_table_t*)((unsigned int) tab | 3 | 4)); //Writeable/present + usermode 81 | 82 | int i; 83 | for(i = 0; i < 1024; i++){ 84 | tab->pages[i].frame = phys >> 12; 85 | tab->pages[i].present = 1; 86 | tab->pages[i].user = 1; 87 | phys += 4096; 88 | } 89 | } 90 | 91 | void vpage_fault(registers_t* regs){ 92 | cli(); 93 | if(current_proc != NULL){ 94 | memcpy(¤t_proc->registers, regs, sizeof(registers_t)); 95 | dump_proc(current_proc); 96 | susp_proc(current_proc->pid); 97 | 98 | vga_fmt("In process %d:\n", current_proc->pid); 99 | WARN("segfault, halting process"); 100 | scheduler(regs); 101 | } 102 | 103 | vga_set_fg(RED); 104 | 105 | unsigned int err_pos; 106 | asm volatile ("mov %%cr2, %0" : "=r" (err_pos)); 107 | 108 | vga_puts("Page fault occurred at "); 109 | vga_puts_hex(err_pos); 110 | 111 | vga_puts("\nReasons:"); 112 | 113 | int no_page = regs->err_code & 1; 114 | int rw = regs->err_code & 2; 115 | int um = regs->err_code & 4; 116 | int re = regs->err_code & 8; 117 | int dc = regs->err_code & 16; 118 | 119 | if(dc) vga_puts(" (Instruction decode error) "); 120 | if(!no_page) vga_puts(" (No page present) "); 121 | if(um) vga_puts(" (in user mode) "); 122 | if(rw) vga_puts(" (Write permissions) "); 123 | if(re) vga_puts(" (RE) "); 124 | 125 | vga_puts("\n"); 126 | 127 | if(current_proc == NULL){ 128 | PANIC("vpage fault in before multitasking started"); 129 | } 130 | } 131 | 132 | void virtix_page_init(){ 133 | current_vpage_dir = mk_vpage_dir(); 134 | root_vpage_dir = current_vpage_dir; 135 | 136 | unsigned int i; 137 | for(i = 0; i < 0xF0000000; i += PAGE_S) 138 | vpage_map(root_vpage_dir, i, i); 139 | 140 | register_interrupt_handler(14, vpage_fault); 141 | cli(); 142 | switch_vpage_dir(root_vpage_dir); 143 | } 144 | 145 | void convert_vpage(vpage_dir_t* kdir){ 146 | int i; 147 | for(i = 0; i < 1024; i++){ 148 | kdir->tables[i] = (page_table_t*) ((unsigned int) kdir->tables[i] | 4); //Set usermode bit 149 | 150 | if(((unsigned int) kdir->tables[i]) & 1){ //The page is present 151 | int j; 152 | for(j = 0; j < 1024; j++) 153 | kdir->tables[i]->pages[j].user = 1; //Make every page within run in usermode 154 | } 155 | } 156 | } 157 | 158 | void dump_page(vpage_dir_t* dir, unsigned int address){ 159 | unsigned short id = address >> 22; 160 | DISP("Index salt =", (unsigned int) dir->tables[id]); 161 | } 162 | 163 | vpage_dir_t* copy_user_dir(vpage_dir_t* dir){ 164 | uint i; 165 | 166 | vpage_dir_t* copy = mk_vpage_dir(); 167 | memcpy(copy, root_vpage_dir, sizeof(vpage_dir_t)); 168 | 169 | for(i = 0; i < 1024; i++){ 170 | if(((uint) dir->tables[i]) & 4){ 171 | //vga_fmt("Found a user page at index %d\n", i); 172 | page_table_t* tab = (page_table_t*) ((uint) dir->tables[i] & 0xFFFFF000); 173 | //vga_fmt("Table at address %X maps to %X\n", (uint) tab, i << 22); 174 | //vga_fmt("Virtually mapped from %X\n", tab->pages[0].frame << 12); 175 | 176 | void* buffer = kmalloc_a(PAGE_S); 177 | memcpy(buffer, (void*) (tab->pages[0].frame << 12), PAGE_S); 178 | vpage_map_user(copy, (uint) buffer, (uint) i << 22); 179 | } 180 | } 181 | 182 | return copy; 183 | } 184 | -------------------------------------------------------------------------------- /src/virtix_proc.c: -------------------------------------------------------------------------------- 1 | #include "common.h" 2 | #include "monitor.h" 3 | #include "virtix_proc.h" 4 | #include "clock.h" 5 | #include "isr.h" 6 | #include "virtix_page.h" 7 | #include "single.h" 8 | #include "kheap.h" 9 | #include "file.h" 10 | 11 | unsigned int pid = 0; 12 | 13 | virtix_proc_t* root; 14 | virtix_proc_t* current_proc = NULL; 15 | 16 | registers_t hold_root; 17 | 18 | extern unsigned int stack_hold; 19 | 20 | void scheduler(registers_t* regs){ 21 | memcpy(¤t_proc->registers, regs, sizeof(registers_t)); 22 | 23 | //NOTIFY("task switch"); 24 | 25 | virtix_clock(regs); 26 | 27 | current_proc = current_proc->next; 28 | if(current_proc == NULL){ 29 | current_proc = root; 30 | } 31 | 32 | while(current_proc->state == PROC_ASLEEP){ 33 | current_proc = current_proc->next; 34 | if(current_proc == NULL) 35 | current_proc = root; 36 | } 37 | 38 | memcpy(regs, ¤t_proc->registers, sizeof(registers_t)); 39 | switch_vpage_dir(current_proc->cr3); 40 | } 41 | 42 | void init_procs(virtix_proc_t* proc){ 43 | root = proc; 44 | root->pid = pid++; 45 | root->next = NULL; 46 | root->thread = PROC_ROOT; //Unkillable 47 | root->state = PROC_RUNNING; 48 | 49 | current_proc = root; 50 | register_interrupt_handler(32, scheduler); 51 | enter_userspace(proc); 52 | } 53 | 54 | void kill_proc(unsigned int pid){ 55 | virtix_proc_t* proc = pid_to_proc(pid); 56 | 57 | if(proc == PID_NOT_FOUND) 58 | PANIC("can't kill unknown PID"); 59 | 60 | kfflush(proc->stdout); 61 | kfflush(proc->stderr); 62 | proc->state = PROC_ASLEEP; 63 | 64 | if(proc->parent != NULL){ 65 | //NOTIFY("Child had parent (!!!)"); 66 | //wake_proc(proc->parent->pid); 67 | } 68 | } 69 | 70 | unsigned int spawn_proc(virtix_proc_t* process){ 71 | process->next = root->next; 72 | root->next = process; 73 | process->state = PROC_RUNNING; 74 | 75 | process->parent = current_proc; 76 | 77 | //susp_proc(current_proc->pid); 78 | 79 | return process->pid; 80 | } 81 | 82 | //Find out if a child process has died 83 | int wait_gid(uint gid, int* status){ 84 | virtix_proc_t* i = root; 85 | 86 | while(i != NULL){ 87 | if(i->gid == gid) 88 | if(i->state == PROC_ASLEEP){ 89 | *status = i->registers.ebx; 90 | return i->pid; 91 | } 92 | 93 | i = i->next; 94 | } 95 | 96 | return WAIT_OKAY; 97 | } 98 | 99 | //Find out if a process has died 100 | int wait_pid(uint pid, int* status){ 101 | virtix_proc_t* i = current_proc->next; 102 | 103 | while(i != NULL){ 104 | if(i->pid == pid) 105 | if(i->state == PROC_ASLEEP){ 106 | *status = i->registers.ebx; 107 | return i->pid; 108 | } 109 | else 110 | return WAIT_OKAY; 111 | i = i->next; 112 | } 113 | 114 | return WAIT_ERROR; 115 | } 116 | 117 | void susp_proc(unsigned int pid){ 118 | virtix_proc_t* proc = pid_to_proc(pid); 119 | 120 | if(proc == PID_NOT_FOUND){ 121 | WARN("couldn't find PID for suspension"); 122 | return; 123 | } 124 | 125 | proc->state = PROC_ASLEEP; 126 | } 127 | 128 | void wake_proc(unsigned int pid){ 129 | virtix_proc_t* proc = pid_to_proc(pid); 130 | 131 | if(proc == PID_NOT_FOUND) 132 | return; 133 | 134 | proc->state = PROC_RUNNING; 135 | } 136 | 137 | unsigned int child_proc(virtix_proc_t* child, unsigned int pid){ 138 | susp_proc(pid); 139 | 140 | virtix_proc_t* parent = pid_to_proc(pid); 141 | 142 | if(parent == PID_NOT_FOUND){ 143 | PANIC("child process spawned in without parent"); 144 | } 145 | 146 | child->parent = parent; 147 | 148 | return spawn_proc(child); 149 | } 150 | 151 | unsigned int fork_proc(unsigned int pid){ 152 | WARN("dummy stub"); 153 | return pid++; 154 | } 155 | 156 | virtix_proc_t* pid_to_proc(unsigned int pid){ 157 | virtix_proc_t* proc = root; 158 | 159 | while(proc != NULL){ 160 | if(proc->pid == pid) 161 | return proc; 162 | 163 | proc = proc->next; 164 | } 165 | 166 | return PID_NOT_FOUND; 167 | } 168 | 169 | virtix_proc_t* mk_empty_proc(){ 170 | virtix_proc_t* proc = (virtix_proc_t*) kmalloc_a(sizeof(virtix_proc_t)); 171 | proc->registers.cs = 0x1B; 172 | proc->registers.ds = 0x23; 173 | proc->registers.ss = 0x23; 174 | proc->cr3 = mk_vpage_dir(); 175 | 176 | proc->brk = 0x50000000; 177 | 178 | int i; 179 | for(i = 0; i < 1024; i++) 180 | proc->cr3->tables[i] = root_vpage_dir->tables[i]; 181 | 182 | proc->pid = pid++; 183 | 184 | return proc; 185 | } 186 | 187 | void dump_proc(virtix_proc_t* proc){ 188 | vga_puts("Process '"); 189 | vga_puts(proc->name); 190 | vga_puts("' with PID "); 191 | vga_puts_hex(proc->pid); 192 | vga_puts(" before last call to scheduler:"); 193 | 194 | vga_puts("\nEAX="); 195 | vga_puts_hex(proc->registers.eax); 196 | vga_puts("\tEBX="); 197 | vga_puts_hex(proc->registers.ebx); 198 | vga_puts("\tECX="); 199 | vga_puts_hex(proc->registers.ecx); 200 | vga_puts("\tEDX="); 201 | vga_puts_hex(proc->registers.edx); 202 | 203 | vga_puts("\nEDI="); 204 | vga_puts_hex(proc->registers.edi); 205 | vga_puts("\tESI="); 206 | vga_puts_hex(proc->registers.esi); 207 | vga_puts("\tEBP="); 208 | vga_puts_hex(proc->registers.ebp); 209 | vga_puts("\tESP="); 210 | vga_puts_hex(proc->registers.esp); 211 | 212 | vga_puts("\nDS ="); 213 | vga_puts_hex(proc->registers.ds); 214 | vga_puts("\tCS ="); 215 | vga_puts_hex(proc->registers.cs); 216 | vga_puts("\tSS ="); 217 | vga_puts_hex(proc->registers.ss); 218 | vga_puts("\tUSP="); 219 | vga_puts_hex(proc->registers.useresp); 220 | 221 | vga_puts("\n*EFLAGS*="); 222 | vga_puts_hex(proc->registers.eflags); 223 | vga_puts("\t*EIP*="); 224 | vga_puts_hex(proc->registers.eip); 225 | 226 | vga_puts("\t*CR3*="); 227 | vga_puts_hex((unsigned int) proc->cr3); 228 | vga_puts("/"); 229 | 230 | unsigned int cr3; 231 | asm volatile ("mov %%cr3, %0" : "=r" (cr3)); 232 | vga_puts_hex(cr3); 233 | 234 | vga_puts("\n"); 235 | } 236 | -------------------------------------------------------------------------------- /userland/.gitignore: -------------------------------------------------------------------------------- 1 | *.img *.o .*.swp 2 | -------------------------------------------------------------------------------- /userland/link.ld: -------------------------------------------------------------------------------- 1 | ENTRY(_start) 2 | SECTIONS 3 | { 4 | /*This is the text section, note start position*/ 5 | .text 0x40000000: 6 | { 7 | code = .; _code = .; __code = .; 8 | *(.text) 9 | } 10 | 11 | /*This is the data section, note 4MB alignment*/ 12 | .data ALIGN(0x400000): 13 | { 14 | data = .; _data = .; __data = .; 15 | *(.data) 16 | *(.rodata) 17 | } 18 | 19 | .bss ALIGN(0x400000): 20 | { 21 | bss = .; _bss = .; __bss = .; 22 | *(.bss) 23 | } 24 | 25 | end = .; _end = .; __end = .; 26 | } 27 | -------------------------------------------------------------------------------- /userland/makefile: -------------------------------------------------------------------------------- 1 | CFLAGS = -m32 -nostdlib -nostdinc -fno-builtin -fno-stack-protector -I../libc/include -g 2 | LDFLAGS = -Tlink.ld -melf_i386 3 | CC = i686-elf-gcc 4 | LD = i686-elf-ld 5 | SOURCES = $(wildcard src/*.c) 6 | OUTPUTS = $(SOURCES:.c=.o) 7 | EXECS = $(OUTPUTS:.o=) 8 | LIBC = ../libc/libc.a 9 | 10 | all: binclean $(EXECS) 11 | 12 | $(OUTPUTS): $(SOURCES) 13 | $(CC) $(CFLAGS) $(@:.o=.c) -c -o $@ 14 | 15 | $(EXECS): $(OUTPUTS) 16 | $(LD) $(LDFLAGS) $@.o $(LIBC) -o $@ 17 | strip --strip-unneeded $@ 18 | mv $@ bin/ 19 | 20 | disk: 21 | cp mkdf.sh bin 22 | if ! [ -e hdd.img ]; \ 23 | then \ 24 | dd if=/dev/zero of=hdd.img bs=512 count=219328; \ 25 | fi 26 | /sbin/mkdosfs -F16 -f1 -R1 -a hdd.img 27 | bin/mkdf.sh . hdd.img 28 | 29 | binclean: 30 | -rm $(OUTPUTS) 31 | -rm bin/* 32 | -rm *.x16 33 | 34 | clean: binclean 35 | -rm *.img *.vdi 36 | 37 | gfx.x16: 38 | nasm -fbin gfx.asm -o gfx.x16 39 | -------------------------------------------------------------------------------- /userland/mkdf.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | 5 | target=$1 6 | image=$2 7 | count=0 8 | 9 | if ! [ -d $target ]; then 10 | echo mkdf needs a valid directory to create 11 | exit -1 12 | fi 13 | 14 | if ! [ -a $image ]; then 15 | echo mkdf needs a valid image to create vfs 16 | fi 17 | 18 | image=$(readlink -f $image) 19 | target=$(readlink -f $target) 20 | cd $target 21 | 22 | inc_count () { 23 | let "count += 1" 24 | } 25 | 26 | init_dir () { 27 | touch $1.DIR 28 | echo DEEPFAT > $1.DIR 29 | echo DEEPDIR >> $1.DIR 30 | } 31 | 32 | add_record () { 33 | echo $2 $3 $4 >> $1.DIR 34 | } 35 | 36 | dinit_dir () { 37 | echo END >> $1.DIR 38 | } 39 | 40 | mkdf_dir () { 41 | pushd . 42 | init_dir $2 43 | local tpath=$(readlink -f $1) 44 | local tfile=$(readlink -f $2) 45 | local parent=$(readlink -f $3) 46 | cd $tpath 47 | 48 | for i in $(ls); do 49 | echo Packaging $i... 50 | 51 | if [ -d $i ]; then 52 | if [ "${i##*.}" = DIR ]; then 53 | continue 54 | fi 55 | 56 | inc_count 57 | add_record $tfile DIR $i $count.DIR 58 | local hold=$count.DIR 59 | mkdf_dir $i $count $hold 60 | else 61 | if [ $i = hdd.img ]; then 62 | continue 63 | fi 64 | 65 | inc_count 66 | add_record $tfile FIL $i $count.FIL 67 | mcopy -i $image $i ::/$count.FIL 68 | fi 69 | done 70 | 71 | mv *.DIR $target || true 72 | popd 73 | } 74 | 75 | mkdf_dir $target DFATROOT DFATROOT.DIR 76 | 77 | cd $target 78 | for i in *.DIR; do 79 | echo ENDDIR >> $i 80 | done 81 | 82 | mcopy -i $image *.DIR ::/ 83 | rm *.DIR 84 | echo deepFAT loaded. 85 | -------------------------------------------------------------------------------- /userland/src/asserter.c: -------------------------------------------------------------------------------- 1 | #include "assert.h" 2 | 3 | int main(char** argc, int argv){ 4 | assert(1 == 0); 5 | } 6 | -------------------------------------------------------------------------------- /userland/src/badsh.c: -------------------------------------------------------------------------------- 1 | #include "unistd.h" 2 | #include "stdio.h" 3 | #include "string.h" 4 | #include "stdbool.h" 5 | #include "sys/stat.h" 6 | 7 | char inbuffer[256]; 8 | 9 | void collapse_input(char* str); 10 | void prompt(char* str); 11 | void split(char* str); 12 | char* iter(char* str, char* end); 13 | void exec_builtin(); 14 | void badsh_error(char* msg); 15 | bool file_exists(char* path); 16 | 17 | int main(char** argv, int argc){ 18 | while(true){ 19 | prompt("badsh> "); 20 | exec_builtin(); 21 | } 22 | 23 | return 0; 24 | } 25 | 26 | 27 | //Remove the backspaces from a string 28 | void collapse_input(char* str){ 29 | int len = strlen(str); 30 | 31 | int i, j; 32 | for(i = 0; i < len; i++) 33 | if(str[i] == '\b') 34 | for(j = i; j < len; j++) 35 | str[j] = str[j + 1]; 36 | 37 | } 38 | 39 | //Update inbuffer with a given text prompt 40 | void prompt(char* str){ 41 | printf("%s", str); 42 | char* ret = fgets(inbuffer, 255, stdin); 43 | if(ret == NULL){ 44 | puts("Bye!"); 45 | exit(0); 46 | } 47 | collapse_input(inbuffer); 48 | } 49 | 50 | //Replace all spaces, tabs and newlines with delimiting 0's 51 | void split(char* str){ 52 | int len = strlen(str); 53 | 54 | int i; 55 | for(i = 0; i < len; i++) 56 | if((str[i] == '\t') || (str[i] == ' ') || (str[i] == '\n')) 57 | str[i] = 0; 58 | } 59 | 60 | //Iterate over a split string until end is reached 61 | char* iter(char* str, char* end){ 62 | str += strlen(str); 63 | while(str < end){ 64 | str++; 65 | if(*str != 0) 66 | return str; 67 | } 68 | 69 | return NULL; 70 | } 71 | 72 | //Split the line up and try to execute it 73 | void exec_builtin(){ 74 | char* end = &inbuffer[strlen(inbuffer)]; 75 | split(inbuffer); 76 | char* str = inbuffer; 77 | 78 | if(strlen(str) == 0) 79 | puts(""); 80 | 81 | else if(strcmp("echo", str) == 0){ 82 | str = iter(str, end); 83 | while(str != NULL){ 84 | printf("%s ", str); 85 | str = iter(str, end); 86 | } 87 | 88 | putchar('\n'); 89 | } 90 | 91 | else if(strcmp("exec", str) == 0){ 92 | str = iter(str, end); 93 | if(str == NULL) 94 | badsh_error("exec needs an argument"); 95 | 96 | if(file_exists(str) == 0){ 97 | badsh_error("file not found"); 98 | return; 99 | } 100 | 101 | int status; 102 | if(fork() == 0) 103 | exec(str); 104 | 105 | else{ 106 | wait(&status); 107 | printf("program returned %d exit status.\n", status); 108 | } 109 | } 110 | 111 | else 112 | badsh_error("unknown command"); 113 | 114 | //Clear the buffer 115 | int i; 116 | for(i = 0; i < 256; i++) 117 | inbuffer[i] = 0; 118 | } 119 | 120 | //Display an error msg 121 | void badsh_error(char* msg){ 122 | printf("! Badsh error: %s\n", msg); 123 | } 124 | 125 | bool file_exists(char* path){ 126 | struct stat buffer; 127 | return stat(path, &buffer) == 0; 128 | } 129 | -------------------------------------------------------------------------------- /userland/src/error.c: -------------------------------------------------------------------------------- 1 | #include "stdio.h" 2 | 3 | int main(char** argv, int argc){ 4 | return -1; 5 | } 6 | -------------------------------------------------------------------------------- /userland/src/escaper.c: -------------------------------------------------------------------------------- 1 | #include "stdio.h" 2 | 3 | int main(char** argv, int argc){ 4 | printf("Testing an escape.\x1b[0;31m Done.\n"); 5 | printf("Resetting. \x1b[0mDone.\n"); 6 | } 7 | -------------------------------------------------------------------------------- /userland/src/faulter.c: -------------------------------------------------------------------------------- 1 | #include "stdio.h" 2 | #include "unistd.h" 3 | 4 | int main(char** argv, int argc){ 5 | printf("Going to segfault with pid %d\n", getpid()); 6 | *((uint*) 0) = 123123; 7 | return 0; 8 | } 9 | -------------------------------------------------------------------------------- /userland/src/forker.c: -------------------------------------------------------------------------------- 1 | #include "unistd.h" 2 | #include "stdio.h" 3 | #include "sys/wait.h" 4 | 5 | int main(char** argc, int argv){ 6 | int f; 7 | printf("Starting program with pid %d\n", getpid()); 8 | printf("Fork returned %d\n", f = fork()); 9 | 10 | int x; 11 | 12 | 13 | if(f == 0) 14 | wait(&x); 15 | else 16 | exec("/bin/hello"); 17 | 18 | 19 | printf("pid %d done.\n", getpid()); 20 | 21 | if(f == 0) 22 | printf("Child returned %d.\n", x); 23 | 24 | return -1; 25 | } 26 | -------------------------------------------------------------------------------- /userland/src/hello.c: -------------------------------------------------------------------------------- 1 | #include "unistd.h" 2 | #include "stdio.h" 3 | void break_program(); 4 | 5 | int main(char** argc, int argv){ 6 | printf("Hello, world! I am PID %d in GID %d.\n", getpid(), getgid()); 7 | return 0; 8 | } 9 | 10 | void break_program(){ 11 | *((unsigned int*) 0xFFFFFFFF) = 1; 12 | } 13 | -------------------------------------------------------------------------------- /userland/src/mallocer.c: -------------------------------------------------------------------------------- 1 | #include "stdio.h" 2 | #include "stdlib.h" 3 | 4 | int main(char** argv, int argc){ 5 | void* x = malloc(10); 6 | printf("Malloc'd 10 bytes at %X\n", (uint) x); 7 | free(x); 8 | printf("Freed\n"); 9 | 10 | return 0; 11 | } 12 | -------------------------------------------------------------------------------- /userland/src/reader.c: -------------------------------------------------------------------------------- 1 | #include "unistd.h" 2 | #include "stdio.h" 3 | 4 | int main(char** argv, int argc){ 5 | puts("Going to read a line from a file"); 6 | 7 | char buffer[128]; 8 | FILE* f = open("/makefile", 0); 9 | fgets(buffer, 127, f); 10 | puts("fgets'd into buffer"); 11 | printf("Read this line: %s\n", buffer); 12 | puts("Done."); 13 | return 0; 14 | } 15 | -------------------------------------------------------------------------------- /userland/src/spawner.c: -------------------------------------------------------------------------------- 1 | #include "unistd.h" 2 | #include "stdio.h" 3 | 4 | int main(char** argv, int argc){ 5 | exec("/bin/hello"); 6 | printf("Successfully spawned subprocess!\n"); 7 | } 8 | -------------------------------------------------------------------------------- /userland/src/typer.c: -------------------------------------------------------------------------------- 1 | #include "stdio.h" 2 | #include "unistd.h" 3 | 4 | int main(char** argv, int argc){ 5 | FILE* f = (FILE*) open("/test.txt", 0); 6 | 7 | print("Mash some keys! > "); 8 | 9 | char c; 10 | 11 | for(;;){ 12 | fputc(f, c = fgetc(stdin)); 13 | if(c == 'x') 14 | break; 15 | } 16 | 17 | close(f); 18 | puts("\nDone."); 19 | sync(); 20 | 21 | return 0; 22 | } 23 | -------------------------------------------------------------------------------- /userland/src/waiter.c: -------------------------------------------------------------------------------- 1 | #include "stdio.h" 2 | #include "sys/wait.h" 3 | #include "unistd.h" 4 | 5 | int main(char** argv, int argc){ 6 | int stat; 7 | 8 | if(fork()){ 9 | exec("/bin/hello"); 10 | return 0; 11 | } 12 | 13 | waitpid(-1, &stat, 0); 14 | return 0; 15 | } 16 | --------------------------------------------------------------------------------