├── LICENSE ├── Makefile ├── crt0.c ├── hd └── MyFile ├── initrd └── hw.c ├── initrd_src ├── Makefile ├── bf.c ├── cat.c ├── clear.c ├── cyc.c ├── echo.c ├── ext2chk.c ├── forktest.c ├── ft.c ├── hw.c ├── init.c ├── login.c ├── ls.c ├── m.c ├── malloctest.c ├── mbr.c ├── mount.c ├── sayhi.c ├── shell.c ├── shell2.c ├── sig.c ├── syntax.c ├── title.c ├── tokenizer.h └── ubasic.h ├── iso └── boot │ └── grub │ └── grub.cfg ├── kernel ├── Makefile ├── Makefile.cfg ├── boot.asm ├── cpu │ ├── Makefile │ ├── cpu.asm │ ├── gdt.c │ ├── idt.c │ ├── irq.c │ └── isr.c ├── devices │ ├── Makefile │ ├── ata.c │ ├── console.c │ ├── devman.c │ ├── fpu.c │ ├── kbd.c │ ├── mouse.c │ ├── pipedev.c │ ├── pit.c │ ├── ramdev.c │ └── ttydev.c ├── fs │ ├── Makefile │ ├── devfs.c │ ├── ext2.c │ ├── fsman.c │ ├── initramfs.c │ └── vfs.c ├── include │ ├── ata.h │ ├── config.h │ ├── console.h │ ├── debug.h │ ├── devfs.h │ ├── device.h │ ├── elf.h │ ├── ext2.h │ ├── font.h │ ├── fpu.h │ ├── gdt.h │ ├── idt.h │ ├── initramfs.h │ ├── io.h │ ├── isr.h │ ├── kbd.h │ ├── kmem.h │ ├── multiboot.h │ ├── pipe.h │ ├── pit.h │ ├── process.h │ ├── scheduler.h │ ├── serial.h │ ├── signal.h │ ├── string.h │ ├── sys │ │ └── types.h │ ├── syscall.h │ ├── system.h │ ├── tty.h │ ├── utypes.h │ ├── va_list.h │ ├── vbe.h │ └── vfs.h ├── kernel.c ├── link.ld ├── mem │ ├── Makefile │ └── kmem.c ├── misc │ ├── Makefile │ ├── debug.c │ ├── io.c │ ├── serial.c │ └── string.c ├── obj │ └── .bashrc └── sys │ ├── Makefile │ ├── process.c │ ├── scheduler.c │ ├── signal.c │ └── syscall.c └── libc ├── Makefile ├── include ├── fcntl.h ├── signal.h ├── stdio.h ├── stdlib.h ├── system.h └── unistd.h └── src ├── fcntl.c ├── signal.c ├── stdio.c ├── stdlib.c ├── system.c └── unistd.c /Makefile: -------------------------------------------------------------------------------- 1 | include kernel/Makefile.cfg 2 | 3 | cd: cd.iso 4 | 5 | NODIR = --no-print-directory 6 | 7 | cd.iso: kernel/kernel.elf libc/libc.a iso/initrd hd.img 8 | @cp kernel/kernel.elf iso/ 9 | @grub2-mkrescue iso/ -o cd.iso &>/dev/null 10 | @echo -e "\033[0;32mcd.iso is ready\033[0m" 11 | 12 | kernel/kernel.elf: 13 | @cd kernel; make $(NODIR) 14 | 15 | iso/initrd: 16 | @rm -f -r initrd/dev 17 | @mkdir initrd/dev 18 | @cd initrd_src; make $(NODIR) 19 | 20 | libc/libc.a: 21 | @cd libc; make $(NODIR) 22 | 23 | hd.img: 24 | @echo -e "\033[0;34mCreating hd.img\n\033[0;31m"\ 25 | "NOTE : hd.img is created only once, you need to update it manualy\033[0m" 26 | @touch hd.img 27 | @dd if=/dev/zero of=hd.img bs=1MiB count=64 &>/dev/null 28 | @mkfs.ext2 hd.img &>/dev/null 29 | @rm -f -r tmp 30 | @mkdir tmp 31 | @sudo mount hd.img tmp 32 | @sudo chmod 777 tmp/. 33 | @cp hd/* tmp/ -rf 34 | @sudo umount tmp 35 | @rm tmp -rf 36 | 37 | OBJ = iso/kernel.elf iso/initrd cd.iso 38 | clean: 39 | @echo -e "\033[0;34mCleaning kernel/\033[0m" 40 | @cd kernel; make clean $(NODIR) 41 | @echo -e "\033[0;34mCleaning libc/\033[0m" 42 | @cd libc; make clean $(NODIR) 43 | @echo -e "\033[0;34mCleaning iso/\033[0m" 44 | ${RM} -f $(OBJ) 45 | 46 | try: cd.iso 47 | qemu-system-x86_64 -cdrom cd.iso -m 1G -serial stdio -hda hd.img -enable-kvm -boot d 48 | -------------------------------------------------------------------------------- /crt0.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | //extern void exit(int code); 9 | extern int main (int argc, char **argv); 10 | 11 | #define syscall2(call, arg0, arg1) \ 12 | asm("int $0x80;":: "a"(call), "b"(arg0), "c"(arg1)); 13 | 14 | int getatt(int req, char *buf) 15 | { 16 | syscall2(13, req, buf); 17 | } 18 | 19 | void _start() { 20 | int argslen = getatt(0, NULL); 21 | char *args = malloc(argslen + 1); 22 | memset(args, 0, argslen); 23 | getatt(1, args); 24 | 25 | int i, argc = 0, envc = 0; 26 | char *_ = args; 27 | while(*_) 28 | { 29 | ++argc; 30 | _ = _ + strlen(_) + 1; 31 | } 32 | 33 | char *argv[argc + 1]; 34 | char *arg = args; 35 | for(i = 0; i < argc; ++i) 36 | { 37 | argv[i] = arg; 38 | arg += strlen(arg) + 1; 39 | } 40 | 41 | argv[argc] = NULL; 42 | 43 | int envslen = getatt(2, NULL); 44 | char *envs = malloc(envslen + 1); 45 | memset(envs, 0, envslen); 46 | getatt(3, envs); 47 | 48 | _ = envs; 49 | while(*_) 50 | { 51 | ++envc; 52 | _ = _ + strlen(_) + 1; 53 | } 54 | 55 | char *envv[envc + 1]; 56 | char *env = envs; 57 | 58 | for(i = 0; i < envc; ++i) 59 | { 60 | envv[i] = env; 61 | env += strlen(env) + 1; 62 | } 63 | 64 | envv[envc] = NULL; 65 | 66 | extern char **environ; 67 | environ = envv; 68 | 69 | //_init_signal(); 70 | int ex = main(argc, argv); 71 | exit(ex); 72 | } 73 | -------------------------------------------------------------------------------- /hd/MyFile: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thethumbler/os/f15788e9a7f5822a23e24d7f610fa55e432ac7db/hd/MyFile -------------------------------------------------------------------------------- /initrd/hw.c: -------------------------------------------------------------------------------- 1 | #include 2 | int main() 3 | { 4 | printf("\033[0;33mHello, World!\n\033[0m"); 5 | } 6 | -------------------------------------------------------------------------------- /initrd_src/Makefile: -------------------------------------------------------------------------------- 1 | include ../kernel/Makefile.cfg 2 | 3 | APPS = init login shell hw echo clear title syntax sayhi cat mbr ls sig \ 4 | bf malloctest ext2chk mount 5 | 6 | all: $(APPS) 7 | @echo -n -e "\033[1;33mCreating initrd : \033[1;31m" 8 | @cd ../initrd; find . | cpio -H bin -o > ../iso/initrd 9 | @echo -n -e "\033[0m" 10 | 11 | % : %.c 12 | @echo -n -e "\033[1;33mCC " $< "\033[1;31m" 13 | @~/myos/bin/x86_64-elektros-gcc $< -o ../initrd/bin/$@ -std=c99 14 | @echo -e "\033[0m" 15 | 16 | #~/myos/bin/tcc $< ../mymalloc.o -o ../initrd/$@ 17 | #strip ../initrd/$@ 18 | #$(CC) $(CFLAGS) -z max-page-size=0x1000 -nostdlib -Wl,-Ttext,0x0 \ 19 | #-fno-builtin -ffreestanding -w $< ~/myos/usr/lib/crt1.o ../mymalloc.o \ 20 | #~/myos/usr/lib/libc.a -o ../initrd/$@ -I ~/myos/usr/include \ 21 | -------------------------------------------------------------------------------- /initrd_src/bf.c: -------------------------------------------------------------------------------- 1 | /* 2 | Brainfuck-C ( http://github.com/kgabis/brainfuck-c ) 3 | Copyright (c) 2012 Krzysztof Gabis 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 13 | all 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 21 | THE SOFTWARE. 22 | */ 23 | 24 | /* This is a modified version of the original program in order to work with 25 | our OS. 26 | */ 27 | 28 | #include 29 | #include 30 | #include 31 | #include 32 | 33 | #define OP_END 0 34 | #define OP_INC_DP 1 35 | #define OP_DEC_DP 2 36 | #define OP_INC_VAL 3 37 | #define OP_DEC_VAL 4 38 | #define OP_OUT 5 39 | #define OP_IN 6 40 | #define OP_JMP_FWD 7 41 | #define OP_JMP_BCK 8 42 | 43 | #define SUCCESS 0 44 | #define FAILURE 1 45 | 46 | #define PROGRAM_SIZE 512 47 | #define STACK_SIZE 512 48 | #define DATA_SIZE 512 49 | 50 | #define STACK_PUSH(A) (STACK[SP++] = A) 51 | #define STACK_POP() (STACK[--SP]) 52 | #define STACK_EMPTY() (SP == 0) 53 | #define STACK_FULL() (SP == STACK_SIZE) 54 | 55 | struct instruction_t { 56 | unsigned short operator; 57 | unsigned short operand; 58 | }; 59 | 60 | static struct instruction_t PROGRAM[PROGRAM_SIZE]; 61 | static unsigned short STACK[STACK_SIZE]; 62 | static unsigned int SP = 0; 63 | static char *str = 0; 64 | static char *_str; 65 | 66 | int exec_bf() 67 | { 68 | str = _str; 69 | *str = '\0'; 70 | 71 | unsigned short data[DATA_SIZE], pc = 0; 72 | unsigned int ptr = DATA_SIZE; 73 | while (--ptr) { data[ptr] = 0; } 74 | while (PROGRAM[pc].operator != OP_END && ptr < DATA_SIZE) { 75 | switch (PROGRAM[pc].operator) { 76 | case OP_INC_DP: ptr++; break; 77 | case OP_DEC_DP: ptr--; break; 78 | case OP_INC_VAL: data[ptr]++; break; 79 | case OP_DEC_VAL: data[ptr]--; break; 80 | case OP_OUT: *str++ = data[ptr]; break; 81 | case OP_IN: /*data[ptr] = (unsigned int)getchar();*/ break; // XXX 82 | case OP_JMP_FWD: if(!data[ptr]) { pc = PROGRAM[pc].operand; } break; 83 | case OP_JMP_BCK: if(data[ptr]) { pc = PROGRAM[pc].operand; } break; 84 | default: return FAILURE; 85 | } 86 | pc++; 87 | } 88 | 89 | if(*_str) 90 | { 91 | *str = '\0'; 92 | write(1, _str, DATA_SIZE); 93 | } 94 | 95 | return ptr != DATA_SIZE ? SUCCESS : FAILURE; 96 | } 97 | 98 | int compile_bf(int fd) { 99 | unsigned short pc = 0, jmp_pc; 100 | 101 | int c; 102 | while ((c = *str++) != 0 && pc < PROGRAM_SIZE) 103 | { 104 | switch (c) { 105 | case '>': PROGRAM[pc].operator = OP_INC_DP; break; 106 | case '<': PROGRAM[pc].operator = OP_DEC_DP; break; 107 | case '+': PROGRAM[pc].operator = OP_INC_VAL; break; 108 | case '-': PROGRAM[pc].operator = OP_DEC_VAL; break; 109 | case '.': PROGRAM[pc].operator = OP_OUT; break; 110 | case ',': PROGRAM[pc].operator = OP_IN; break; 111 | case '[': 112 | PROGRAM[pc].operator = OP_JMP_FWD; 113 | if (STACK_FULL()) { 114 | return FAILURE; 115 | } 116 | STACK_PUSH(pc); 117 | break; 118 | case ']': 119 | if (STACK_EMPTY()) { 120 | return FAILURE; 121 | } 122 | jmp_pc = STACK_POP(); 123 | PROGRAM[pc].operator = OP_JMP_BCK; 124 | PROGRAM[pc].operand = jmp_pc; 125 | PROGRAM[jmp_pc].operand = pc; 126 | break; 127 | default: pc--; break; 128 | } 129 | pc++; 130 | } 131 | 132 | if (!STACK_EMPTY() || pc == PROGRAM_SIZE) { 133 | return FAILURE; 134 | } 135 | PROGRAM[pc].operator = OP_END; 136 | return SUCCESS; 137 | } 138 | 139 | int main(int argc, char **argv) 140 | { 141 | if(argc != 2) 142 | { 143 | printf("usage: %s filename\n", argv[0]); 144 | } 145 | int fd = open(argv[1], 0); 146 | str = malloc(1000); 147 | _str = str; 148 | int size = read(fd, str, 1000); 149 | 150 | int status = compile_bf(fd); 151 | 152 | close(fd); 153 | 154 | if(status == SUCCESS) 155 | { 156 | exec_bf(); 157 | } 158 | else 159 | { 160 | write(1, "Error!\n", 7); 161 | } 162 | 163 | _exit(0); 164 | for(;;); 165 | } 166 | -------------------------------------------------------------------------------- /initrd_src/cat.c: -------------------------------------------------------------------------------- 1 | /* This file is part of ToaruOS and is released under the terms 2 | * of the NCSA / University of Illinois License - see LICENSE.md 3 | * Copyright (C) 2013-2014 Kevin Lange 4 | */ 5 | /* 6 | * cat 7 | * 8 | * Concatenates files together to standard output. 9 | * In a supporting terminal, you can then pipe 10 | * standard out to another file or other useful 11 | * things like that. 12 | */ 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | #define CHUNK_SIZE 4096 19 | 20 | void doit(int fd) { 21 | while (1) { 22 | char buf[CHUNK_SIZE]; 23 | memset(buf, 0, CHUNK_SIZE); 24 | ssize_t r = read(fd, buf, CHUNK_SIZE); 25 | if (!r) return; 26 | write(STDOUT_FILENO, buf, r); 27 | } 28 | } 29 | 30 | int main(int argc, char ** argv) { 31 | int ret = 0; 32 | if (argc == 1) { 33 | doit(0); 34 | } 35 | 36 | for (int i = 1; i < argc; ++i) { 37 | int fd = open(argv[i], O_RDONLY); 38 | if (fd == -1) { 39 | fprintf(stderr, "%s: %s: no such file or directory\n", argv[0], argv[i]); 40 | ret = 1; 41 | continue; 42 | } 43 | 44 | struct stat _stat; 45 | fstat(fd, &_stat); 46 | 47 | if (S_ISDIR(_stat.st_mode)) { 48 | fprintf(stderr, "%s: %s: Is a directory\n", argv[0], argv[i]); 49 | close(fd); 50 | ret = 1; 51 | continue; 52 | } 53 | 54 | doit(fd); 55 | 56 | close(fd); 57 | } 58 | 59 | return ret; 60 | } 61 | 62 | /* 63 | * vim:tabstop=4 64 | * vim:noexpandtab 65 | * vim:shiftwidth=4 66 | */ 67 | -------------------------------------------------------------------------------- /initrd_src/clear.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() 4 | { 5 | fprintf(stderr, "\033[H\033[2J"); 6 | return 0; 7 | } 8 | -------------------------------------------------------------------------------- /initrd_src/cyc.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | static __inline__ unsigned long long rdtsc(void) 5 | { 6 | unsigned long long int x; 7 | __asm__ volatile (".byte 0x0f, 0x31" : "=A" (x)); 8 | return x; 9 | } 10 | 11 | int main() { 12 | unsigned long long cycles = rdtsc(); //1 13 | cycles = rdtsc() - cycles; //2 14 | printf("Time is %d\n", (unsigned)cycles); 15 | return 0; 16 | } 17 | -------------------------------------------------------------------------------- /initrd_src/echo.c: -------------------------------------------------------------------------------- 1 | /* This file is part of ToaruOS and is released under the terms 2 | * of the NCSA / University of Illinois License - see LICENSE.md 3 | * Copyright (C) 2013-2014 Kevin Lange 4 | */ 5 | /* vim: tabstop=4 shiftwidth=4 noexpandtab 6 | * 7 | * echo 8 | * 9 | * Prints its arguments (with some processing, ask --help) 10 | * to standard out. 11 | */ 12 | #include 13 | #include 14 | 15 | void usage() { 16 | printf("echo [-n] [-e] [STRING]...\n" 17 | " -n do not output a new line at the end\n" 18 | " -e process escape sequences\n"); 19 | } 20 | 21 | int main(int argc, char ** argv) { 22 | int start = 1; 23 | int use_newline = 1; 24 | int process_escapes = 0; 25 | 26 | for (int i = start; i < argc; ++i) { 27 | if (argv[i][0] != '-') { 28 | start = i; 29 | break; 30 | } else { 31 | if (argv[i][1] == 'h') { 32 | usage(); 33 | return 1; 34 | } else if (argv[i][1] == 'n') { 35 | use_newline = 0; 36 | } else if (argv[i][1] == 'e') { 37 | process_escapes = 1; 38 | } 39 | } 40 | } 41 | 42 | for (int i = start; i < argc; ++i) { 43 | if (process_escapes) { 44 | for (int j = 0; j < strlen(argv[i]) - 1; ++j) { 45 | if (argv[i][j] == '\\') { 46 | if (argv[i][j+1] == 'e') { 47 | argv[i][j] = '\033'; 48 | for (int k = j + 1; k < strlen(argv[i]); ++k) { 49 | argv[i][k] = argv[i][k+1]; 50 | } 51 | } 52 | if (argv[i][j+1] == 'n') { 53 | argv[i][j] = '\n'; 54 | for (int k = j + 1; k < strlen(argv[i]); ++k) { 55 | argv[i][k] = argv[i][k+1]; 56 | } 57 | } 58 | } 59 | } 60 | } 61 | printf("%s",argv[i]); 62 | if (i != argc - 1) { 63 | printf(" "); 64 | } 65 | } 66 | 67 | if (use_newline) { 68 | printf("\n"); 69 | } 70 | 71 | fflush(stdout); 72 | return 0; 73 | } 74 | -------------------------------------------------------------------------------- /initrd_src/ext2chk.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main(int argc, char **argv) 5 | { 6 | if(argc < 2 || argc > 3) 7 | { 8 | printf("usage: %s filename [count]\n", argv[0]); 9 | return -1; 10 | } 11 | 12 | FILE *file = fopen(argv[1], "r"); 13 | //fseek(file, 1024*1024, SEEK_SET); 14 | 15 | unsigned i, count = argc == 3 ? atoi(argv[2]) : 1024; 16 | for(i = 0; i < count; ++i) 17 | { 18 | unsigned short sig; 19 | fread((void*)&sig, 2, 1, file); 20 | if(sig == 0xEF53) 21 | printf("%u: %X\n", i/512, sig); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /initrd_src/forktest.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main(int argc, char **argv) 6 | { 7 | if(argc != 2) 8 | { 9 | printf("usage: %s tests_count\n", argv[0]); 10 | return -1; 11 | } 12 | 13 | int tests = atoi(argv[1]), i; 14 | for(i = 0; i < tests; ++i) 15 | { 16 | int a; 17 | if(a = fork()) 18 | { 19 | fprintf(stderr, "spawned child %d\n", a); 20 | } 21 | else 22 | for(;;); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /initrd_src/ft.c: -------------------------------------------------------------------------------- 1 | /* example1.c */ 2 | /* */ 3 | /* This small program shows how to print a rotated string with the */ 4 | /* FreeType 2 library. */ 5 | 6 | 7 | #include 8 | #include 9 | //#include 10 | 11 | #include 12 | #include FT_FREETYPE_H 13 | 14 | 15 | #define WIDTH 80 16 | #define HEIGHT 24 17 | 18 | 19 | /* origin is the upper left corner */ 20 | unsigned char image[HEIGHT][WIDTH]; 21 | 22 | 23 | /* Replace this function with something useful. */ 24 | 25 | void 26 | draw_bitmap( FT_Bitmap* bitmap, 27 | FT_Int x, 28 | FT_Int y) 29 | { 30 | FT_Int i, j, p, q; 31 | FT_Int x_max = x + bitmap->width; 32 | FT_Int y_max = y + bitmap->rows; 33 | 34 | 35 | for ( i = x, p = 0; i < x_max; i++, p++ ) 36 | { 37 | for ( j = y, q = 0; j < y_max; j++, q++ ) 38 | { 39 | if ( i < 0 || j < 0 || 40 | i >= WIDTH || j >= HEIGHT ) 41 | continue; 42 | 43 | image[j][i] |= bitmap->buffer[q * bitmap->width + p]; 44 | } 45 | } 46 | } 47 | 48 | 49 | void 50 | show_image( void ) 51 | { 52 | int i, j; 53 | 54 | 55 | for ( i = 0; i < HEIGHT; i++ ) 56 | { 57 | for ( j = 0; j < WIDTH; j++ ) 58 | putchar( image[i][j] == 0 ? ' ' 59 | : image[i][j] < 128 ? '+' 60 | : '*' ); 61 | putchar( '\n' ); 62 | } 63 | } 64 | 65 | 66 | int 67 | main( int argc, 68 | char** argv ) 69 | { 70 | FT_Library library; 71 | FT_Face face; 72 | 73 | FT_GlyphSlot slot; 74 | FT_Matrix matrix; /* transformation matrix */ 75 | FT_Vector pen; /* untransformed origin */ 76 | FT_Error error; 77 | 78 | char* filename; 79 | char* text; 80 | 81 | double angle; 82 | int target_height; 83 | int n, num_chars; 84 | 85 | 86 | if ( argc != 2 ) 87 | { 88 | fprintf ( stderr, "usage: %s sample-text\n", argv[0] ); 89 | exit( 1 ); 90 | } 91 | 92 | filename = "/ubm.ttf"; /* first argument */ 93 | text = argv[1]; /* second argument */ 94 | num_chars = strlen( text ); 95 | angle = 0; /* use 25 degrees */ 96 | target_height = HEIGHT; 97 | 98 | error = FT_Init_FreeType( &library ); /* initialize library */ 99 | fprintf(stderr, "error %X\n", error); 100 | /* error handling omitted */ 101 | 102 | int fd = open(filename, 0); 103 | int sz = lseek(fd, 0, SEEK_END); 104 | lseek(fd, 0, SEEK_SET); 105 | void *buf = malloc(sz + 20); 106 | read(fd, buf, 100); 107 | 108 | error = FT_New_Memory_Face(library, buf, sz, 0, &face); /* create face object */ 109 | fprintf(stderr, "error %X\n", error); 110 | 111 | /* use 50pt at 100dpi */ 112 | error = FT_Set_Char_Size( face, 50 * 64, 0, 113 | 50, 0 ); /* set character size */ 114 | fprintf(stderr, "set\n"); 115 | /* error handling omitted */ 116 | 117 | slot = face->glyph; 118 | 119 | /* set up matrix */ 120 | matrix.xx = (FT_Fixed)( 1 * 0x10000L ); 121 | matrix.xy = (FT_Fixed)(-0 * 0x10000L ); 122 | matrix.yx = (FT_Fixed)( 0 * 0x10000L ); 123 | matrix.yy = (FT_Fixed)( 1 * 0x10000L ); 124 | 125 | /* the pen position in 26.6 cartesian space coordinates; */ 126 | /* start at (300,200) relative to the upper left corner */ 127 | pen.x = 0; 128 | pen.y = ( target_height - 24 ) * 64; 129 | 130 | fprintf(stderr, "Get Ready\n"); 131 | for ( n = 0; n < num_chars; n++ ) 132 | { 133 | /* set transformation */ 134 | FT_Set_Transform( face, &matrix, &pen ); 135 | fprintf(stderr, "Trans\n"); 136 | 137 | /* load glyph image into the slot (erase previous one) */ 138 | error = FT_Load_Char( face, text[n], FT_LOAD_RENDER ); 139 | fprintf(stderr, "Load\n"); 140 | if ( error ) 141 | continue; /* ignore errors */ 142 | 143 | /* now, draw to our target surface (convert position) */ 144 | draw_bitmap( &slot->bitmap, 145 | slot->bitmap_left, 146 | target_height - slot->bitmap_top ); 147 | fprintf(stderr, "draw\n"); 148 | 149 | /* increment pen position */ 150 | pen.x += slot->advance.x; 151 | pen.y += slot->advance.y; 152 | } 153 | 154 | show_image(); 155 | 156 | FT_Done_Face ( face ); 157 | FT_Done_FreeType( library ); 158 | 159 | return 0; 160 | } 161 | 162 | /* EOF */ 163 | -------------------------------------------------------------------------------- /initrd_src/hw.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() 4 | { 5 | printf("\033[0;33mHello, World!\n\033[0m"); 6 | } 7 | -------------------------------------------------------------------------------- /initrd_src/init.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | void main() 6 | { 7 | if(!fork()) 8 | { 9 | execve("/bin/login", NULL, NULL); 10 | open("/dev/tty/0", 0); 11 | write(0, "login not found\n", 17); 12 | _exit(0); 13 | } 14 | //uint64_t status; 15 | //wait(&status); 16 | for(;;); 17 | } 18 | -------------------------------------------------------------------------------- /initrd_src/login.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #define WIDTH 80 7 | #define HEIGHT 25 8 | #define POS(str) ((WIDTH - strlen(str))/2) 9 | 10 | #define SETCUR(r, c) \ 11 | { \ 12 | char __buf__[9]; \ 13 | sprintf(__buf__, "\033[%d;%dH", r, c); \ 14 | fprintf(stderr, __buf__);\ 15 | } 16 | 17 | #define SETCOL(color) \ 18 | { \ 19 | char __buf__[7]; \ 20 | sprintf(__buf__, "\033[%dm", color); \ 21 | fprintf(stderr, __buf__);\ 22 | } 23 | 24 | int main() 25 | { 26 | open("/dev/tty/0", 0); 27 | open("/dev/tty/0", 0); 28 | open("/dev/tty/0", 0); 29 | 30 | char *welcome_msg = 31 | "=======================[ Welcome to the yet un-named OS ]======================="; 32 | SETCOL(36); 33 | fprintf(stderr, "\n\n%s\n", welcome_msg); 34 | SETCOL(0); 35 | 36 | fprintf(stderr, "Currently any user name shall work ;)\n"); 37 | char usr[80]; 38 | while(!usr[0] || usr[0] == '\n') 39 | { 40 | fprintf(stderr, "username : "); 41 | read(0, usr, 80); 42 | } 43 | 44 | int i; 45 | for(i = 0; usr[i] != '\n'; ++i); 46 | usr[i] = 0; 47 | 48 | char _usr[80]; 49 | strcat(_usr, "USER="); 50 | strcat(_usr, usr); 51 | 52 | char *env[] = { _usr, "PWD=/", NULL }; 53 | execve("/bin/shell", NULL, env); 54 | } 55 | -------------------------------------------------------------------------------- /initrd_src/ls.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main(int argc, char **argv) 6 | { 7 | char *cwd; 8 | if(argc != 2) 9 | cwd = getcwd(NULL, 50); 10 | else 11 | cwd = argv[1]; 12 | 13 | DIR *dir = opendir(cwd); 14 | struct dirent *ent = NULL; 15 | while(ent = readdir(dir)) 16 | printf("%s\n", ent->d_name); 17 | } 18 | -------------------------------------------------------------------------------- /initrd_src/m.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #define humanize(val) \ 7 | ((val) > 1000000 ? (val)/1000000 : (val) > 1000 ? (val)/1000 : (val)) 8 | #define size(val) \ 9 | ((val) > 1000000 ? "MiB" : (val) > 1000 ? "KiB" : "B") 10 | 11 | void dum(); 12 | 13 | int main(int argc, char **argv) 14 | { 15 | if(argc != 3) 16 | { 17 | printf("usage: %s block_size tests_count\n", argv[0]); 18 | return -1; 19 | } 20 | 21 | size_t bs = atoll(argv[1]); 22 | 23 | switch(argv[1][strlen(argv[1]) - 1]) 24 | { 25 | case 'g': 26 | case 'G': 27 | bs *= 1000000000; 28 | break; 29 | case 'm': 30 | case 'M': 31 | bs *= 1000000; 32 | break; 33 | case 'k': 34 | case 'K': 35 | bs *= 1000; 36 | break; 37 | } 38 | 39 | unsigned a = atoi(argv[2]), i; 40 | 41 | int failed = 0; 42 | 43 | for(i = 0; i < a; ++i) 44 | { 45 | uint8_t *ptr = malloc(bs); 46 | *ptr = 'A'; 47 | //memset(ptr, 'A', bs); 48 | int r = 0;//memcmp(ptr, main, (uint64_t)dum - (uint64_t)main); 49 | //if(*ptr != 'A') r = 1; 50 | //if(r) ++failed; 51 | printf("[%6d] : 0x%016lX (%s)\n", i, ptr, r?"failed":"passed"); 52 | int s = 0; 53 | } 54 | 55 | printf("Memory test %s with %d test(s) [%u %s]\n", failed?"failed":"passed", 56 | a, humanize(a * bs), size(a * bs)); 57 | //*(char*)(-1) = 5; // break kernel 58 | } 59 | 60 | void dum() 61 | { 62 | 63 | } 64 | -------------------------------------------------------------------------------- /initrd_src/malloctest.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | void dum(); 7 | int main(int argc, char **argv) 8 | { 9 | if(argc < 2 || argc > 4) 10 | { 11 | printf("usage: %s size [count] [skip_free]\n", argv[0]); 12 | exit(0); 13 | } 14 | 15 | int size = atoi(argv[1]); 16 | 17 | switch(argv[1][strlen(argv[1]) - 1]) 18 | { 19 | case 'g': 20 | case 'G': 21 | size *= 1000000000; 22 | break; 23 | case 'm': 24 | case 'M': 25 | size *= 1000000; 26 | break; 27 | case 'k': 28 | case 'K': 29 | size *= 1000; 30 | break; 31 | } 32 | 33 | int count = argc >= 3 ? atoi(argv[2]) : 1; 34 | int skip_free = argc >= 4 ? atoi(argv[3]) : 1; 35 | int i = 0, failed = 0, fail = 0; 36 | while(count--) 37 | { 38 | void *ptr = malloc(size); 39 | //if(count || i) fprintf(stderr, "[%04d]: ", i++); 40 | //fprintf(stderr, "malloc(%d) = 0x%016lX ", size, ptr); 41 | int msize = (int)((void*)dum - (void*)main); 42 | memcpy(ptr, main, msize); 43 | if(memcmp(ptr, main, msize)) ++failed; 44 | /* 45 | int j; 46 | for(j = 0; j < size; ++j) 47 | if(*(char*)(ptr+j) != 'A') 48 | */ 49 | 50 | //printf("(%s)\n", failed ? "failed" : "passed"); 51 | fail += failed; 52 | failed = 0; 53 | if(!(++i%skip_free)) free(ptr); 54 | } 55 | fprintf(stderr, "malloc: %d test(s) %s\n", i, fail ? "failed":"passed"); 56 | //*(char*)(-1) = 'A'; 57 | _exit(0); 58 | } 59 | 60 | void dum() 61 | { 62 | 63 | } 64 | -------------------------------------------------------------------------------- /initrd_src/mbr.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #define MBR_STATUS_NON_BOOTABLE 0x00 6 | #define MBR_STATUS_NON_BOOTABLE_LBA 0x01 7 | #define MBR_STATUS_BOOTABLE 0x80 8 | #define MBR_STATUS_BOOTABLE_LBA 0x81 9 | 10 | #define MBR_TYPE_UNUSED 0x00 11 | #define MBR_TYPE_EXTENDED_DOS 0x05 12 | #define MBR_TYPE_NTFS 0x07 13 | #define MBR_TYPE_EXTENDED_WINDOWS 0x0F 14 | #define MBR_TYPE_LINUX_SWAP 0x82 15 | #define MBR_TYPE_LINUX 0x83 16 | 17 | #define MBR_COPY_PROTECTED 0x5A5A 18 | 19 | #define MBR_BOOT_SIGNATURE 0xAA55 20 | 21 | #pragma pack(1) 22 | 23 | typedef struct { 24 | uint8_t status; 25 | struct { 26 | uint8_t h; 27 | uint16_t cs; 28 | } start_chs; 29 | uint8_t type; 30 | struct { 31 | uint8_t h; 32 | uint16_t cs; 33 | } end_chs; 34 | uint32_t starting_lba; 35 | uint32_t number_of_sectors; 36 | } partition_t; 37 | 38 | typedef struct { 39 | uint8_t bootstrap_code[440]; 40 | uint32_t disk_signiture; 41 | uint16_t copy_protected; 42 | partition_t partition_table[4]; 43 | uint16_t boot_signature; 44 | } mbr_t; 45 | 46 | #pragma pack() 47 | 48 | void print_partition_geom(partition_t part){ 49 | 50 | uint16_t s; 51 | uint16_t c; 52 | fprintf(stdout, " - start chs:\n"); 53 | s = part.start_chs.cs & 0x3F; 54 | c = (part.start_chs.cs & 0xFFC0) >> 6; 55 | fprintf(stdout, " - c:%u h:%u s:%u", 56 | c, 57 | part.start_chs.h, 58 | s); 59 | if(part.start_chs.h == 254 && s == 63 && c == 1023){ 60 | fprintf(stdout, " (size > 8GB)\n"); 61 | }else{ 62 | fprintf(stdout, "\n"); 63 | } 64 | 65 | fprintf(stdout, " - ending chs:\n"); 66 | s = part.end_chs.cs & 0x3F; 67 | c = (part.end_chs.cs & 0xFFC0) >> 6; 68 | fprintf(stdout, " - c:%u h:%u s:%u", 69 | c, 70 | part.end_chs.h, 71 | s); 72 | if(part.end_chs.h == 254 && s == 63 && c == 1023){ 73 | fprintf(stdout, " (size > 8GB)\n"); 74 | }else{ 75 | fprintf(stdout, "\n"); 76 | } 77 | 78 | 79 | fprintf(stdout, " - starting lba: %u\n", part.starting_lba); 80 | fprintf(stdout, " - ending lba: %u\n", part.starting_lba + part.number_of_sectors - 1); 81 | fprintf(stdout, " - sectors: %u \n", part.number_of_sectors); 82 | } 83 | 84 | void print_partition_status(uint8_t status){ 85 | fprintf(stdout, " - status: "); 86 | if (status == MBR_STATUS_BOOTABLE) { 87 | fprintf(stdout, "bootable\n"); 88 | return; 89 | } 90 | if (status == MBR_STATUS_NON_BOOTABLE) { 91 | fprintf(stdout, "non-bootable\n"); 92 | return; 93 | } 94 | if (status == MBR_STATUS_BOOTABLE_LBA) { 95 | fprintf(stdout, "bootable lba\n"); 96 | return; 97 | } 98 | if (status == MBR_STATUS_NON_BOOTABLE_LBA) { 99 | fprintf(stdout, "non-bootable lba\n"); 100 | return; 101 | } 102 | fprintf(stdout, "invalid partition status\n"); 103 | } 104 | 105 | void print_partition_type(uint8_t type){ 106 | fprintf(stdout, " - type: "); 107 | switch (type) { 108 | case MBR_TYPE_UNUSED: 109 | fprintf(stdout, "unused\n"); 110 | break; 111 | case MBR_TYPE_NTFS: 112 | fprintf(stdout, "ntfs\n"); 113 | break; 114 | case MBR_TYPE_LINUX_SWAP: 115 | fprintf(stdout, "linux-swap\n"); 116 | break; 117 | case MBR_TYPE_LINUX: 118 | fprintf(stdout, "linux\n"); 119 | break; 120 | case MBR_TYPE_EXTENDED_DOS: 121 | fprintf(stdout, "extended-doc\n"); 122 | break; 123 | case MBR_TYPE_EXTENDED_WINDOWS: 124 | fprintf(stdout, "extended-windows\n"); 125 | break; 126 | default: 127 | fprintf(stdout, "unknown\n"); 128 | break; 129 | } 130 | } 131 | 132 | int main(int argc, char** argv){ 133 | if(argc != 2){ 134 | fprintf(stderr,"Usage: %s \n",argv[0]); 135 | return EXIT_FAILURE; 136 | } 137 | 138 | FILE *mbr_fd = fopen(argv[1], "r"); 139 | if(mbr_fd == NULL){ 140 | fprintf(stderr, "Error opening mbr file\n"); 141 | return EXIT_FAILURE; 142 | } 143 | 144 | mbr_t mbr; 145 | if(fread((void *)&mbr, 1, sizeof(mbr_t), mbr_fd) != sizeof(mbr_t)){ 146 | fprintf(stderr,"Error reading mbr\n"); 147 | return EXIT_FAILURE; 148 | } 149 | 150 | if(mbr.boot_signature != MBR_BOOT_SIGNATURE){ 151 | fprintf(stderr,"No valid bootsector found\n"); 152 | return EXIT_FAILURE; 153 | } 154 | 155 | for(int i = 0; i < 4; ++i){ 156 | if(mbr.partition_table[i].type == MBR_TYPE_UNUSED){ 157 | continue; 158 | } 159 | fprintf(stdout,"Partition %d\n", i); 160 | print_partition_status(mbr.partition_table[i].status); 161 | print_partition_type(mbr.partition_table[i].type); 162 | print_partition_geom(mbr.partition_table[i]); 163 | } 164 | 165 | return EXIT_SUCCESS; 166 | } 167 | -------------------------------------------------------------------------------- /initrd_src/mount.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main(int argc, char **argv) 5 | { 6 | if(argc < 3 || argc > 4) 7 | { 8 | printf("usage: %s fs [src] dst\n", argv[0]); 9 | return -1; 10 | } 11 | 12 | char *fs = argv[1]; 13 | char *dst = argc == 4 ? argv[3] : argv[2]; 14 | char *src = argc == 4 ? argv[2] : NULL; 15 | 16 | switch(mount(src, dst, fs, 0, NULL)) 17 | { 18 | case -2: 19 | printf("unkown filesystem: %s\n", fs); 20 | return -2; 21 | case -3: 22 | printf("destination not found: %s\n", dst); 23 | return -3; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /initrd_src/sayhi.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define SETCOL(color) \ 4 | { \ 5 | char __buf__[7]; \ 6 | sprintf(__buf__, "\033[%dm", color); \ 7 | fprintf(stderr, __buf__);\ 8 | } 9 | 10 | int main(int argc, char **argv) 11 | { 12 | if(argc != 2) return -1; 13 | 14 | SETCOL(46); 15 | SETCOL(30); 16 | 17 | fprintf(stderr, "Welcome %s, nice to see you ;)\n", argv[1]); 18 | 19 | SETCOL(0); 20 | } 21 | -------------------------------------------------------------------------------- /initrd_src/shell.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | int main(int argc, char **argv) 11 | { 12 | signal(SIGINT, SIG_IGN); 13 | 14 | char buf[100]; 15 | chdir("/"); 16 | while(1) 17 | { 18 | fprintf(stderr, "[ %s : %s ] # ", getenv("USER"), getcwd(NULL, 50)); 19 | memset(buf, 0, 100); 20 | read(0, buf, 100); 21 | 22 | char *tokens[20], *p = buf; 23 | 24 | int i = 0; 25 | tokens[0] = p; 26 | 27 | if(*p == '\n') continue; 28 | while(*p != '\n' && i < 20) 29 | { 30 | if(*p == ' ') 31 | { 32 | *p = '\0'; 33 | ++p; 34 | 35 | if(*p == '\"') // Quotes protected argument.. let's take them out 36 | { 37 | *p = '\0'; 38 | tokens[++i] = ++p; 39 | --p; 40 | while(*++p && *p != '\"'); 41 | *p = '\0'; 42 | ++p; 43 | continue; 44 | } 45 | 46 | if(*p != '\n') 47 | tokens[++i] = p; 48 | } 49 | else 50 | ++p; 51 | } 52 | 53 | tokens[++i] = NULL; 54 | 55 | if(*p == '\n') { *p = '\0'; *++p = '\0'; } 56 | 57 | if(!strcmp(tokens[0], "cd")) // Change directory 58 | { 59 | if(tokens[1][0] == '/') // Canonical path 60 | { 61 | chdir(tokens[1]); 62 | } else 63 | { 64 | char *cwd = getcwd(NULL, 50); 65 | char *path = malloc(strlen(cwd) + strlen(tokens[1]) + 1); 66 | strcat(path, cwd); 67 | strcat(path + strlen(cwd), tokens[1]); 68 | free(cwd); 69 | chdir(path); 70 | free(path); 71 | } 72 | continue; 73 | } 74 | 75 | const char *bin = "/bin/"; 76 | 77 | if(!fork()) // in Child 78 | { 79 | // Let's tokenize the buffer 80 | char _pname[strlen(bin) + strlen(tokens[0]) + 1]; 81 | memset(_pname, 0, sizeof(_pname)); 82 | strcat(_pname, bin); 83 | strcat(_pname + strlen(bin), tokens[0]); 84 | 85 | char *pname = _pname; 86 | 87 | extern char **environ; 88 | execve(pname, &tokens[1], environ); 89 | 90 | fprintf(stderr, "%s : command not found\n", tokens[0]); 91 | exit(0); 92 | for(;;); // We should never reach this anyway 93 | } 94 | int stat; 95 | wait(&stat); 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /initrd_src/shell2.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | void main() 6 | { 7 | if(fork()) _exit(0); 8 | 9 | close(0); 10 | close(1); 11 | close(2); 12 | open("/dev/tty1", 0); 13 | open("/dev/tty1", 0); 14 | open("/dev/tty1", 0); 15 | 16 | char buf[100]; 17 | while(1) 18 | { 19 | write(0, "Shell # ", 8); 20 | read(0, buf, 100); 21 | if(*buf == '/') // Trying to start an application 22 | { 23 | if(!fork()) // in Child 24 | { 25 | // Let's take out the newline character 26 | uint64_t i; 27 | for(i = 0; i < 100; ++i) 28 | if(buf[i] == '\n') 29 | { 30 | buf[i] = '\0'; 31 | break; 32 | } 33 | execve(buf, 0, 0); 34 | for(;;); // We should never reach this anyway 35 | } 36 | uint64_t stat; 37 | wait(&stat); 38 | } 39 | else 40 | write(0, buf, 100); 41 | } 42 | for(;;); 43 | } 44 | -------------------------------------------------------------------------------- /initrd_src/sig.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | void handler(int _) 5 | { 6 | printf("in signal\n"); 7 | } 8 | 9 | int main() 10 | { 11 | printf("Registering handler\n"); 12 | signal(SIGUSR1, handler); 13 | raise(SIGUSR1); 14 | } 15 | 16 | -------------------------------------------------------------------------------- /initrd_src/syntax.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #define SETCOL(col) \ 5 | { char ___buf[6]; sprintf(___buf, "\033[%dm", col); fprintf(stderr, ___buf); } 6 | 7 | char color[] = { 36, 35, 33, 92 }; 8 | 9 | char *kwrds[] = { "auto", "char", "const", "double", "extern", 10 | "float", "int", "long", "register", "short", 11 | "signed", "static", "unsigned", "void", "volatile", "\0", 12 | 13 | "sizeof", "\0" 14 | 15 | "break", "case", "continue", "default", "do", 16 | "else", "enum", "for", "goto", "if", "return", 17 | "struct", "switch", "typedef", "union", "while", "\0", 18 | 19 | "#include", "\0", 20 | NULL 21 | }; 22 | 23 | int within(char chr, char *str) 24 | { 25 | while(*str) 26 | if(chr == *str++) 27 | return 1; 28 | return 0; 29 | } 30 | 31 | int main(int argc, char **argv) 32 | { 33 | if(argc != 2) return -1; 34 | 35 | FILE *file = fopen(argv[1], "r"); 36 | fseek(file, 0, SEEK_END); 37 | unsigned size = ftell(file); 38 | fseek(file, 0, SEEK_SET); 39 | 40 | char _buf[size]; 41 | fread(_buf, size, 1, file); 42 | 43 | char *pos = _buf, *buf = _buf; 44 | char br; 45 | 46 | while(*buf) 47 | { 48 | while(*buf && !within(*buf, " \n\t;\"")) ++buf; // Breaks 49 | 50 | br = *buf; 51 | 52 | *buf = '\0'; 53 | 54 | int color_n = 0; 55 | char **kwrd = kwrds; 56 | while(*kwrd) 57 | { 58 | if(!**kwrd) { ++color_n; ++kwrd; continue; } 59 | if(!strcmp(pos, *kwrd++)) 60 | SETCOL(color[color_n]); 61 | } 62 | 63 | fprintf(stderr, "%s\033[0m", pos == buf ? "" : pos); 64 | 65 | if(br == '\"') 66 | { 67 | fprintf(stderr, "\033[32m\""); 68 | pos = ++buf; 69 | 70 | while(*buf != '\"') ++buf; 71 | *buf = '\0'; 72 | fprintf(stderr, "%s\"\033[0m", pos); 73 | pos = ++buf; 74 | continue; 75 | } 76 | 77 | fprintf(stderr, "%c", br); 78 | 79 | pos = ++buf; 80 | } 81 | fprintf(stderr, "\n"); 82 | } 83 | -------------------------------------------------------------------------------- /initrd_src/title.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #define WIDTH 80 5 | #define HEIGHT 25 6 | #define POS(str) ((WIDTH - strlen(str))/2) 7 | 8 | #define SETCUR(r, c) printf("\033[%d;%dH", r, c); 9 | #define SETCOL(col) printf("\033[%dm", col); 10 | int main(int argc, char **argv) 11 | { 12 | if(argc != 2) return -1; 13 | 14 | 15 | SETCUR(1, 1) 16 | SETCOL(42); 17 | SETCOL(30); 18 | 19 | int i; 20 | for(i = 0; i < WIDTH; ++i) 21 | printf(" "); 22 | 23 | SETCUR(1, POS(argv[1])); 24 | printf("[%s]", argv[1]); 25 | SETCOL(0); 26 | SETCUR(2, 1); 27 | } 28 | -------------------------------------------------------------------------------- /initrd_src/tokenizer.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006, Adam Dunkels 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 3. Neither the name of the author nor the names of its contributors 14 | * may be used to endorse or promote products derived from this software 15 | * without specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 | * SUCH DAMAGE. 28 | * 29 | */ 30 | #ifndef __TOKENIZER_H__ 31 | #define __TOKENIZER_H__ 32 | 33 | enum { 34 | TOKENIZER_ERROR, 35 | TOKENIZER_ENDOFINPUT, 36 | TOKENIZER_NUMBER, 37 | TOKENIZER_STRING, 38 | TOKENIZER_VARIABLE, 39 | TOKENIZER_LET, 40 | TOKENIZER_PRINT, 41 | TOKENIZER_IF, 42 | TOKENIZER_THEN, 43 | TOKENIZER_ELSE, 44 | TOKENIZER_FOR, 45 | TOKENIZER_TO, 46 | TOKENIZER_NEXT, 47 | TOKENIZER_GOTO, 48 | TOKENIZER_GOSUB, 49 | TOKENIZER_RETURN, 50 | TOKENIZER_CALL, 51 | TOKENIZER_END, 52 | TOKENIZER_COMMA, 53 | TOKENIZER_SEMICOLON, 54 | TOKENIZER_PLUS, 55 | TOKENIZER_MINUS, 56 | TOKENIZER_AND, 57 | TOKENIZER_OR, 58 | TOKENIZER_ASTR, 59 | TOKENIZER_SLASH, 60 | TOKENIZER_MOD, 61 | TOKENIZER_LEFTPAREN, 62 | TOKENIZER_RIGHTPAREN, 63 | TOKENIZER_LT, 64 | TOKENIZER_GT, 65 | TOKENIZER_EQ, 66 | TOKENIZER_CR, 67 | }; 68 | 69 | void tokenizer_init(const char *program); 70 | void tokenizer_next(void); 71 | int tokenizer_token(void); 72 | int tokenizer_num(void); 73 | int tokenizer_variable_num(void); 74 | void tokenizer_string(char *dest, int len); 75 | 76 | int tokenizer_finished(void); 77 | void tokenizer_error_print(void); 78 | 79 | #endif /* __TOKENIZER_H__ */ 80 | -------------------------------------------------------------------------------- /initrd_src/ubasic.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006, Adam Dunkels 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 3. Neither the name of the author nor the names of its contributors 14 | * may be used to endorse or promote products derived from this software 15 | * without specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 | * SUCH DAMAGE. 28 | * 29 | */ 30 | #ifndef __UBASIC_H__ 31 | #define __UBASIC_H__ 32 | 33 | void ubasic_init(const char *program); 34 | void ubasic_run(void); 35 | int ubasic_finished(void); 36 | 37 | int ubasic_get_variable(int varnum); 38 | void ubasic_set_variable(int varum, int value); 39 | 40 | #endif /* __UBASIC_H__ */ 41 | -------------------------------------------------------------------------------- /iso/boot/grub/grub.cfg: -------------------------------------------------------------------------------- 1 | menuentry "OS" { 2 | multiboot /kernel.elf 3 | module /initrd 4 | } 5 | -------------------------------------------------------------------------------- /kernel/Makefile: -------------------------------------------------------------------------------- 1 | 2 | include Makefile.cfg 3 | 4 | OBJ = boot.o kernel.o 5 | ALL_OBJ = boot.o kernel.o io.o serial.o debug.o string.o kmem.o gdt.o idt.o \ 6 | cpu.o isr.o irq.o vfs.o initramfs.o process.o syscall.o scheduler.o \ 7 | signal.o fpu.o pit.o ramdev.o ttydev.o ext2.o\ 8 | devfs.o console.o kbd.o ata.o devman.o fsman.o 9 | 10 | OUT = obj 11 | 12 | ASFLAGS = -f elf64 13 | CFLAGS = -c -I include/ -mcmodel=large -nostdlib -ffreestanding 14 | LDFLAGS = -T ../link.ld -mcmodel=large -nostdlib -ffreestanding \ 15 | -z max-page-size=0x1000 16 | CPPFLAGS = -I include/ -P 17 | NODIR = --no-print-directory 18 | 19 | kernel.elf: $(OBJ) 20 | ${CP} $(OBJ) $(OUT) 21 | 22 | @cd misc; make $(NODIR) 23 | @cd mem; make $(NODIR) 24 | @cd cpu; make $(NODIR) 25 | @cd fs; make $(NODIR) 26 | @cd sys; make $(NODIR) 27 | @cd devices; make $(NODIR) 28 | @cd obj; $(LD) $(LDFLAGS) $(ALL_OBJ) -o ../$@ 29 | 30 | %.o : %.asm 31 | $(CPP) $(CPPFLAGS) $< -o $<"_tmp__" 32 | $(AS) $(ASFLAGS) -o $@ $<"_tmp__" 33 | @rm $<"_tmp__" 34 | 35 | %.o : %.c 36 | $(CC) $(CFLAGS) $< -o $@ 37 | 38 | clean: 39 | @echo -n -e "\033[0;31m"; \ 40 | cd misc; make clean $(NODIR) 41 | 42 | @echo -n -e "\033[0;31m"; \ 43 | cd mem; make clean $(NODIR) 44 | 45 | @echo -n -e "\033[0;31m"; \ 46 | cd cpu; make clean $(NODIR) 47 | 48 | @echo -n -e "\033[0;31m"; \ 49 | cd fs; make clean $(NODIR) 50 | 51 | @echo -n -e "\033[0;31m"; \ 52 | cd sys; make clean $(NODIR) 53 | 54 | @echo -n -e "\033[0;31m"; \ 55 | cd devices; make clean $(NODIR) 56 | 57 | @rm -f obj/*.o 58 | @rm -f *.o kernel.elf 59 | 60 | -------------------------------------------------------------------------------- /kernel/Makefile.cfg: -------------------------------------------------------------------------------- 1 | AS = @echo -e "\033[0;33mASM" $< "\033[0m"; nasm 2 | CC = @echo -e "\033[0;34mCC " $< "\033[0m"; ~/myos/bin/x86_64-elektros-gcc 3 | LD = echo -e "\033[1;36mLD " $@ "\033[0m"; ~/myos/bin/x86_64-elektros-gcc 4 | CPP = @echo -e "\033[1;33mCPP" $< "\033[0m"; ~/myos/bin/x86_64-elektros-cpp 5 | CP = @echo -e "\033[0;32mCP " $(OBJ) $(OUT) "\033[0m"; cp 6 | RM = @echo -e "\033[0;31mRM " $(OBJ) "\033[0m"; rm 7 | AR = @echo -e "\033[0;31mAR " libc.a "\033[0m"; ~/myos/bin/x86_64-elektros-ar 8 | -------------------------------------------------------------------------------- /kernel/boot.asm: -------------------------------------------------------------------------------- 1 | bits 32 2 | 3 | #include 4 | 5 | section .text 6 | 7 | global _start 8 | 9 | _start: 10 | jmp real_start 11 | align 4 12 | dd 0x1BADB002 13 | #if _GFX_ 14 | dd 7 15 | dd -(0x1BADB002 + 7) 16 | #else 17 | dd 3 18 | dd -(0x1BADB002 + 3) 19 | #endif 20 | times 5 dd 0 21 | dd 0 22 | dd 1024 23 | dd 768 24 | dd 24 25 | 26 | real_start: 27 | mov [mboot_info], ebx 28 | 29 | ; Disable IRQs 30 | ;mov al, 0xFF ; Out 0xFF to 0xA1 and 0x21 to disable all IRQs. 31 | ;out 0xA1, al 32 | ;out 0x21, al 33 | 34 | extern kstart, kend 35 | 36 | ; Get heap address 37 | ; Lets check if any modules are loaded 38 | lea eax, [ ebx + 0x14 ] 39 | mov eax, [eax] 40 | or eax, eax 41 | jz no_modules_found 42 | dec eax 43 | lea ecx, [ ebx + 0x18 ] 44 | mov ecx, [ecx] 45 | mov ebx, 0x10 46 | mul ebx 47 | add eax, ecx 48 | add eax, 0x4 49 | mov eax, [eax] ; Now eax has the end address of the last module 50 | jmp found_modules 51 | 52 | no_modules_found: 53 | mov eax, kend 54 | found_modules: 55 | mov ebx, 0x1000 56 | div ebx 57 | mov ecx, edx 58 | mul ebx 59 | or ecx, ecx 60 | jz .skip 61 | add eax, 0x1000 62 | .skip: 63 | mov [heap_addr], eax 64 | 65 | ; Get bootloader size in pages 66 | xor edx, edx 67 | mov eax, kstart 68 | mov ebx, 0x1000 69 | div ebx 70 | or edx, edx 71 | jz .skip2 72 | inc eax 73 | .skip2: 74 | mov [boot_size], eax 75 | xor edx, edx 76 | mov ebx, 0x200 77 | div ebx 78 | or edx, edx 79 | jz ._skip2 80 | inc eax 81 | ._skip2: 82 | mov [boot_size_ptables], eax 83 | 84 | ; Get total Memory size and set kernel init heap accordingly 85 | mov ebx, [mboot_info] 86 | add ebx, 0x4 87 | mov eax, [ebx] 88 | add ebx, 0x4 89 | add eax, [ebx] 90 | mov ebx, 0xC 91 | mul ebx 92 | mov ebx, 0xA 93 | div ebx ; Now eax holds the size of 120% of memory reported by GrUB 94 | mov ebx, 0x8000000 95 | div ebx 96 | mov [kernel_init_heap], eax 97 | 98 | ; Get kernel size in pages 99 | xor edx, edx 100 | mov eax, [heap_addr] ; Allocate up to heap address 101 | mov ebx, 0x1000 102 | div ebx 103 | or edx, edx 104 | jz .skip3 105 | inc eax 106 | .skip3: 107 | mov ecx, [kernel_init_heap] 108 | mov [kernel_heap_size], ecx 109 | add eax, ecx 110 | mov [kernel_size], eax 111 | xor edx, edx 112 | mov ebx, 0x200 113 | div ebx 114 | or edx, edx 115 | jz ._skip3 116 | inc eax 117 | ._skip3: 118 | mov [kernel_size_ptables], eax 119 | 120 | ; clear boot paging buffer 121 | mov eax, 5 ; PML4, 2 PDPTs, 2 PDs 122 | add eax, [boot_size_ptables] 123 | add eax, [kernel_size_ptables] 124 | mov ebx, 0x1000 125 | mul ebx 126 | mov [heap_size], eax 127 | 128 | mov ecx, eax 129 | xor eax, eax 130 | mov edi, [heap_addr] 131 | rep stosb 132 | 133 | ; Setup PML4 with 2 PDPTs 134 | mov edi, [heap_addr] 135 | ; Setup first PDPT 136 | lea eax, [edi + 0x1000] 137 | or eax, 7 138 | mov [edi], eax 139 | ; Setup second PDPT 140 | add eax, 0x1000 141 | add edi, 0x0FF8 142 | mov [edi], eax 143 | 144 | ; Setup first PDPT with first PD 145 | mov edi, [heap_addr] 146 | lea eax, [edi + 0x3007] 147 | add edi, 0x1000 148 | mov [edi], eax 149 | 150 | ; Setup second PDPT with second PD 151 | mov edi, [heap_addr] 152 | lea eax, [edi + 0x4003] 153 | add edi, 0x2FF8 154 | mov [edi], eax 155 | 156 | ; Setup first PD with required page tables for boot 157 | mov edi, [heap_addr] 158 | lea eax, [edi + 0x5003] 159 | mov ecx, [boot_size_ptables] 160 | add edi, 0x3000 161 | lea esi, [eax - 0x3] 162 | mov [boot_ptable_addr], esi 163 | .loop_first_pd: 164 | mov [edi], eax 165 | add eax, 0x1000 166 | add edi, 8 167 | dec ecx 168 | or ecx, ecx 169 | jnz .loop_first_pd 170 | 171 | ; Setup second PD with required page tables for kernel 172 | mov edi, [heap_addr] 173 | mov eax, [boot_size_ptables] 174 | mov ebx, 0x1000 175 | mul ebx 176 | lea ebx, [edi + 0x5003] 177 | add edi, eax 178 | add eax, ebx 179 | 180 | mov ecx, [kernel_size_ptables] 181 | add edi, 0x3000 182 | lea esi, [eax - 0x3] 183 | mov [kernel_ptable_addr], esi 184 | .loop_second_pd: 185 | mov [edi], eax 186 | add eax, 0x1000 187 | add edi, 8 188 | dec ecx 189 | or ecx, ecx 190 | jnz .loop_second_pd 191 | 192 | ; Setup boot page tables 193 | mov edi, [boot_ptable_addr] 194 | mov eax, 3 195 | mov ecx, [boot_size_ptables] 196 | .boot_ptable_loop: 197 | push ecx 198 | mov ecx, 0x200 199 | .loop_page_table: 200 | mov [edi], eax 201 | add eax, 0x1000 202 | add edi, 8 203 | dec ecx 204 | or ecx, ecx 205 | jnz .loop_page_table 206 | pop ecx 207 | dec ecx 208 | or ecx, ecx 209 | jnz .boot_ptable_loop 210 | 211 | ; Setup kernel page tables 212 | mov edi, [kernel_ptable_addr] 213 | mov eax, 3 214 | mov ecx, [kernel_size_ptables] 215 | .kernel_ptable_loop: 216 | push ecx 217 | mov ecx, 0x200 218 | .kernel_page_table: 219 | mov [edi], eax 220 | add eax, 0x1000 221 | add edi, 8 222 | dec ecx 223 | or ecx, ecx 224 | jnz .kernel_page_table 225 | pop ecx 226 | dec ecx 227 | or ecx, ecx 228 | jnz .kernel_ptable_loop 229 | 230 | mov eax, 10100000b ; Set the PAE and PGE bit. 231 | mov cr4, eax 232 | 233 | mov edx, [heap_addr] ; Point CR3 at the PML4. 234 | mov cr3, edx 235 | 236 | 237 | 238 | mov ecx, 0xC0000080 ; Read from the EFER MSR. 239 | rdmsr 240 | 241 | or eax, 0x00000100 ; Set the LME bit. 242 | wrmsr 243 | 244 | mov ebx, cr0 ; Activate long mode - 245 | or ebx,0x80000001 ; - by enabling paging and protection simultaneously. 246 | mov cr0, ebx 247 | 248 | lgdt [GDT.Pointer] ; Load GDT.Pointer defined below. 249 | 250 | jmp 0x8:longmode ; Load CS with 64 bit segment and flush the instruction cache 251 | 252 | jmp $ 253 | 254 | 255 | %macro GDTE 4 256 | dw %2 & 0xFFFF 257 | dw %1 258 | db %1 >> 16 259 | db %3 260 | db (%2 >> 16) & 0x0F | (%4 << 4) 261 | db %1 >> 24 262 | %endmacro 263 | 264 | %define offset(addr) ( 0x100000 + addr - $$ ) 265 | %macro GDT64 4 266 | dw %2 & 0xFFFF 267 | dw %1 & 0xFFFF 268 | db (%1 >> 16) & 0xFF 269 | db %3 270 | db (%2 >> 16) & 0x0F | (%4 << 4) 271 | db (%1 >> 24) & 0xFF 272 | dd (%1 >> 32) 273 | dd 0 274 | %endmacro 275 | 276 | GDT: 277 | GDTE 0, 0, 0, 0 278 | GDTE 0, 0xfffff, 10011010b, 1010b ; ring0 cs (all mem) 279 | GDTE 0, 0xfffff, 10010010b, 1010b ; ring0 ds (all mem) 280 | GDTE 0, 0xfffff, 11111010b, 1010b ; ring3 cs (all mem), sz=0, L=1 for 64-bit 281 | GDTE 0, 0xfffff, 11110010b, 1010b ; ring3 ds (all mem), sz=0, L=1 for 64-bit 282 | GDT64 0xFFFFFFFFC0000000 + offset(tss64), (end_tss64 - tss64), 11101001b, 0001b 283 | 284 | ALIGN 4 285 | dw 0 286 | .Pointer: 287 | dw $ - GDT - 1 288 | .p: 289 | dd GDT 290 | dd 0 291 | 292 | align 8 293 | ; See "TASK MANAGEMENT IN 64-BIT MODE" of http://download.intel.com/products/processor/manual/325384.pdf 294 | tss64: 295 | dd 0 296 | global k_tss64_sp 297 | k_tss64_sp: 298 | dq 0 ; rsp will be set to this value when switching back to kernel 299 | TIMES 23 dd 0 300 | end_tss64: 301 | 302 | 303 | bits 64 304 | longmode: 305 | mov ax, 0x10 306 | mov ds, ax 307 | mov es, ax 308 | mov fs, ax 309 | mov gs, ax 310 | mov ss, ax 311 | mov rsp, 0xFFFFFFFFC0000000 + stack_end 312 | 313 | mov eax, [GDT.p] 314 | add rax, 0xFFFFFFFFC0000000 315 | mov [GDT.p], rax 316 | lgdt [GDT.Pointer] 317 | 318 | ;jmp $ 319 | 320 | extern kmain 321 | call kmain 322 | jmp $ 323 | 324 | global mboot_info 325 | mboot_info: dq 0 326 | global heap_addr 327 | heap_addr: dd 0 328 | global boot_size 329 | boot_size: dd 0 330 | boot_size_ptables: dd 0 331 | boot_ptable_addr: dd 0 332 | global kernel_size 333 | kernel_size: dd 0 334 | kernel_size_ptables: dd 0 335 | global kernel_ptable_addr 336 | kernel_ptable_addr: dd 0 337 | global kernel_heap_size 338 | kernel_heap_size: dd 0 339 | global kernel_init_heap 340 | kernel_init_heap: dd 0 341 | global heap_size 342 | heap_size: dd 0 343 | 344 | section .bss 345 | stack_start: 346 | resb 8*1024 347 | stack_end: 348 | -------------------------------------------------------------------------------- /kernel/cpu/Makefile: -------------------------------------------------------------------------------- 1 | include ../Makefile.cfg 2 | 3 | OBJ = gdt.o idt.o cpu.o isr.o irq.o 4 | OUT=../obj 5 | 6 | ASFLAGS = -f elf64 7 | CFLAGS = -c -I ../include/ -mcmodel=large -nostdlib -ffreestanding 8 | 9 | all: $(OBJ) 10 | ${CP} $(OBJ) $(OUT) 11 | 12 | %.o : %.asm 13 | @$(AS) $(ASFLAGS) $< -o $@ 14 | 15 | #$(OUT)/%.o: %.c 16 | # @$(CC) $(CFLAGS) $< -o $@ 17 | 18 | clean: 19 | ${RM} -f $(OBJ) 20 | 21 | -------------------------------------------------------------------------------- /kernel/cpu/cpu.asm: -------------------------------------------------------------------------------- 1 | bits 64 2 | 3 | extern gdt_ptr 4 | global gdt_flush 5 | gdt_flush: 6 | mov rax, gdt_ptr 7 | lgdt [rax] 8 | ret 9 | 10 | extern idt_ptr 11 | global idt_flush 12 | idt_flush: 13 | mov rax, idt_ptr 14 | lidt [rax] 15 | ret 16 | 17 | global load_tss 18 | load_tss: 19 | ;extern tss_ptr 20 | ltr [rel tss_ptr] 21 | ret 22 | 23 | tss_ptr: 24 | dw 0x28 25 | 26 | %macro pusha 0 27 | push rax 28 | push rdx 29 | push rcx 30 | push rbx 31 | push rsp 32 | push rbp 33 | push rsi 34 | push rdi 35 | %endmacro 36 | 37 | %macro popa 0 38 | pop rdi 39 | pop rsi 40 | pop rbp 41 | pop rsp 42 | pop rbx 43 | pop rcx 44 | pop rdx 45 | pop rax 46 | %endmacro 47 | 48 | global int_num, err_num 49 | int_num: dq 0 50 | err_num: dq 0 51 | 52 | %macro ISR_NOERR 1 53 | global isr%1 54 | isr%1: 55 | cli 56 | mov [rel err_num], dword 0 57 | mov [rel int_num], dword %1 58 | jmp isr_handler 59 | %endmacro 60 | 61 | %macro ISR_ERR 1 62 | global isr%1 63 | isr%1: 64 | cli 65 | pop rax 66 | mov [rel err_num], rax 67 | mov [rel int_num], dword %1 68 | jmp isr_handler 69 | %endmacro 70 | 71 | ISR_NOERR 0 72 | ISR_NOERR 1 73 | ISR_NOERR 2 74 | ISR_NOERR 3 75 | ISR_NOERR 4 76 | ISR_NOERR 5 77 | ISR_NOERR 6 78 | ISR_NOERR 7 79 | ISR_ERR 8 80 | ISR_NOERR 9 81 | ISR_ERR 10 82 | ISR_ERR 11 83 | ISR_ERR 12 84 | ISR_ERR 13 85 | ISR_ERR 14 86 | ISR_NOERR 15 87 | ISR_NOERR 16 88 | ISR_NOERR 17 89 | ISR_NOERR 18 90 | ISR_NOERR 19 91 | ISR_NOERR 20 92 | ISR_NOERR 21 93 | ISR_NOERR 22 94 | ISR_NOERR 23 95 | ISR_NOERR 24 96 | ISR_NOERR 25 97 | ISR_NOERR 26 98 | ISR_NOERR 27 99 | ISR_NOERR 28 100 | ISR_NOERR 29 101 | ISR_NOERR 30 102 | ISR_NOERR 31 103 | 104 | 105 | %macro push_context 0 106 | push rax 107 | push rdx 108 | push rcx 109 | push rbx 110 | push rbp 111 | push rsi 112 | push rdi 113 | push r8 114 | push r9 115 | push r10 116 | push r11 117 | push r12 118 | push r13 119 | push r14 120 | push r15 121 | %endmacro 122 | 123 | %macro pop_context 0 124 | pop r15 125 | pop r14 126 | pop r13 127 | pop r12 128 | pop r11 129 | pop r10 130 | pop r9 131 | pop r8 132 | pop rdi 133 | pop rsi 134 | pop rbp 135 | pop rbx 136 | pop rcx 137 | pop rdx 138 | ;pop rax ;XXX RAX has to be poped manually 139 | %endmacro 140 | 141 | isr_handler: 142 | push_context 143 | mov rdi, rsp 144 | extern interrupt 145 | call interrupt 146 | pop_context 147 | pop rax 148 | iretq 149 | 150 | global isr128 151 | isr128: 152 | push_context 153 | mov rdi, rsp 154 | extern syscall_int 155 | call syscall_int 156 | pop_context 157 | pop rax 158 | iretq 159 | 160 | 161 | global switch_to_usermode 162 | switch_to_usermode: 163 | cli 164 | mov ax, 0x23 165 | mov ds, ax 166 | mov rax, 0x7FC0000000 ; Stack 167 | push qword 0x23 168 | push rax 169 | pushfq 170 | pop rax 171 | bts rax, 9 172 | push rax 173 | push qword 0x1B 174 | push qword rdi 175 | iretq 176 | 177 | global switch_context 178 | switch_context: 179 | ;pop_context 180 | cli 181 | mov rax, rsp 182 | mov rsp, rdi 183 | pop r15 184 | pop r14 185 | pop r13 186 | pop r12 187 | pop r11 188 | pop r10 189 | pop r9 190 | pop r8 191 | pop rdi 192 | pop rsi 193 | pop rbp 194 | pop rbx 195 | pop rcx 196 | mov rdx, rsp 197 | mov rsp, rax 198 | mov ax, 0x23 199 | mov ds, ax 200 | mov rax, [rdx + 5*0x8] ; rsp 201 | push qword 0x23 202 | push rax 203 | mov rax, [rdx + 4*0x8] ; rflags 204 | bts rax, 9 205 | push rax 206 | push qword 0x1B 207 | mov rax, [rdx + 2*0x8] ; rip 208 | push qword rax 209 | mov rax, [rdx + 1*0x8] ; rax 210 | mov rdx, [rdx] ; rdx 211 | iretq 212 | 213 | %macro IRQ 2 214 | global irq%1 215 | irq%1: 216 | cli 217 | mov [rel err_num], rax 218 | mov [rel int_num], dword %2 219 | jmp irq_stub 220 | %endmacro 221 | 222 | IRQ 0, 32 223 | IRQ 1, 33 224 | IRQ 2, 34 225 | IRQ 3, 35 226 | IRQ 4, 36 227 | IRQ 5, 37 228 | IRQ 6, 38 229 | IRQ 7, 39 230 | IRQ 8, 40 231 | IRQ 9, 41 232 | IRQ 10, 42 233 | IRQ 11, 43 234 | IRQ 12, 44 235 | IRQ 13, 45 236 | IRQ 14, 46 237 | IRQ 15, 47 238 | irq_stub: 239 | push_context 240 | mov rdi, rsp 241 | extern irq_handler 242 | call irq_handler 243 | pop_context 244 | pop rax 245 | iretq 246 | -------------------------------------------------------------------------------- /kernel/cpu/gdt.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | gdt_entry_t gdt[32]; // Stupidly long GDT 5 | 6 | gdt_ptr_t gdt_ptr = { 7 | .limit = sizeof(gdt) - 1, 8 | .base = (uint64_t)&gdt, 9 | }; 10 | 11 | void gdt_set_entry 12 | (uint32_t id, uint32_t base, uint32_t limit, uint8_t access, uint8_t flags) 13 | { 14 | gdt[id] = 15 | (gdt_entry_t) 16 | { 17 | .limit_low = limit & 0xFFFF, 18 | .base_low = base & 0xFFFFFF, 19 | .type = access & 0xF, 20 | .system = 1, // Always one for Non system descriptors 21 | .dpl = (access >> 5) & 3, 22 | .present = (access >> 7) & 1, 23 | .limit_high = (limit >> 16) & 0xF, 24 | .avilable = 1, 25 | .longmode = (flags >> 1) & 1, 26 | .size = ((flags >> 1) & 1)?0:((flags >> 2) & 1), 27 | .gran = (flags >> 3) & 1, 28 | .base_high = base >> 24, 29 | }; 30 | } 31 | 32 | tss64_t tss64; 33 | #define TSS64_AVL 0x9 34 | 35 | void setup_tss(void *_tss64) 36 | { 37 | uint64_t limit = sizeof(tss64); 38 | uint64_t base = (uint64_t)&tss64; 39 | 40 | tss64_seg_t *tss64_seg = (tss64_seg_t*)_tss64; 41 | *tss64_seg = 42 | (tss64_seg_t) 43 | { 44 | .limit_low = limit & 0xFFFF, 45 | .base_low = base & 0xFFFFFF, 46 | .type = TSS64_AVL, 47 | ._0_1 = 0, 48 | .dpl = 3, 49 | .present = 1, 50 | .limit_high = (limit >> 16) & 0xF, 51 | .avilable = 1, 52 | ._0_2 = 0, 53 | .gran = 0, 54 | .base_high = base >> 24, 55 | ._0_3 = 0, 56 | }; 57 | } 58 | 59 | #define ACC_TYPE_CS 0xA 60 | #define ACC_TYPE_DS 0x2 61 | #define ACC_DPL0 0 62 | #define ACC_DPL3 0x60 63 | #define ACC_PRESENT 0x80 64 | 65 | #define FLAGS_L 0x2 66 | #define FLAGS_32 0x4 67 | #define FLAGS_gran 0x8 68 | 69 | void setup_gdt() 70 | { 71 | gdt_set_entry(0, 0, 0, 0, 0); // Null decriptor 72 | gdt_set_entry(1, 0, -1, ACC_TYPE_CS | ACC_DPL0 | ACC_PRESENT, FLAGS_L); // Kernel CS 73 | gdt_set_entry(2, 0, -1, ACC_TYPE_DS | ACC_DPL0 | ACC_PRESENT, FLAGS_L); // Kernel DS 74 | gdt_set_entry(3, 0, -1, ACC_TYPE_CS | ACC_DPL3 | ACC_PRESENT, FLAGS_L); // User CS 75 | gdt_set_entry(4, 0, -1, ACC_TYPE_DS | ACC_DPL3 | ACC_PRESENT, FLAGS_L); // User DS 76 | setup_tss(&gdt[5]); 77 | extern void gdt_flush(void); 78 | gdt_flush(); 79 | } 80 | -------------------------------------------------------------------------------- /kernel/cpu/idt.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | void idt_set_gate( uint32_t id, uint64_t offset, uint16_t sel, uint8_t flags) 5 | { 6 | idt[id].offset_low = (offset >> 0x00) & 0xFFFF; 7 | idt[id].offset_mid = (offset >> 0x10) & 0xFFFF; 8 | idt[id].offset_high = (offset >> 0x20) & 0xFFFFFFFF; 9 | 10 | idt[id].selector = sel; 11 | 12 | idt[id].set_to_0 = 0; 13 | idt[id].flags = flags; 14 | } 15 | 16 | void idt_install() 17 | { 18 | extern void idt_flush(); 19 | idt_ptr.limit = sizeof(idt_entry_t) * 256 - 1; 20 | idt_ptr.base = (uint64_t)&idt; 21 | idt_flush(); 22 | } 23 | -------------------------------------------------------------------------------- /kernel/cpu/irq.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | extern void irq0(void); 6 | extern void irq1(void); 7 | extern void irq2(void); 8 | extern void irq3(void); 9 | extern void irq4(void); 10 | extern void irq5(void); 11 | extern void irq6(void); 12 | extern void irq7(void); 13 | extern void irq8(void); 14 | extern void irq9(void); 15 | extern void irq10(void); 16 | extern void irq11(void); 17 | extern void irq12(void); 18 | extern void irq13(void); 19 | extern void irq14(void); 20 | extern void irq15(void); 21 | 22 | typedef void (*irq_handler_t)(regs_t*); 23 | 24 | static irq_handler_t irq_routines[16] = { NULL }; 25 | 26 | void irq_install_handler(uint32_t irq, irq_handler_t handler) { 27 | irq_routines[irq] = handler; 28 | } 29 | 30 | void irq_uninstall_handler(uint32_t irq) { 31 | irq_routines[irq] = 0; 32 | } 33 | 34 | void irq_remap(void) { 35 | outb(0x20, 0x11); 36 | outb(0xA0, 0x11); 37 | outb(0x21, 0x20); 38 | outb(0xA1, 0x28); 39 | outb(0x21, 0x04); 40 | outb(0xA1, 0x02); 41 | outb(0x21, 0x01); 42 | outb(0xA1, 0x01); 43 | outb(0x21, 0x0); 44 | outb(0xA1, 0x0); 45 | } 46 | 47 | void irq_gates(void) { 48 | idt_set_gate(32, irq0, 0x08, 0x8E); 49 | idt_set_gate(33, irq1, 0x08, 0x8E); 50 | idt_set_gate(34, irq2, 0x08, 0x8E); 51 | idt_set_gate(35, irq3, 0x08, 0x8E); 52 | idt_set_gate(36, irq4, 0x08, 0x8E); 53 | idt_set_gate(37, irq5, 0x08, 0x8E); 54 | idt_set_gate(38, irq6, 0x08, 0x8E); 55 | idt_set_gate(39, irq7, 0x08, 0x8E); 56 | idt_set_gate(40, irq8, 0x08, 0x8E); 57 | idt_set_gate(41, irq9, 0x08, 0x8E); 58 | idt_set_gate(42, irq10, 0x08, 0x8E); 59 | idt_set_gate(43, irq11, 0x08, 0x8E); 60 | idt_set_gate(44, irq12, 0x08, 0x8E); 61 | idt_set_gate(45, irq13, 0x08, 0x8E); 62 | idt_set_gate(46, irq14, 0x08, 0x8E); 63 | idt_set_gate(47, irq15, 0x08, 0x8E); 64 | } 65 | 66 | void irq_install(void) { 67 | irq_remap(); 68 | irq_gates(); 69 | } 70 | 71 | void irq_ack(uint32_t irq_no) { 72 | if (irq_no >= 8) { 73 | outb(0xA0, 0x20); 74 | } 75 | outb(0x20, 0x20); 76 | } 77 | 78 | extern uint32_t int_num; 79 | void irq_handler(regs_t *regs) { 80 | //debug("Recieved IRQ %x\n", int_num); 81 | void (*handler)(regs_t *regs); 82 | if (int_num > 47 || int_num < 32) { 83 | handler = NULL; 84 | } else { 85 | handler = irq_routines[int_num - 32]; 86 | } 87 | if (handler) { 88 | handler(regs); 89 | irq_ack(int_num - 32); 90 | } else { 91 | irq_ack(int_num - 32); 92 | } 93 | } 94 | 95 | void timer(regs_t *regs) 96 | { 97 | static uint32_t counter = 0; 98 | //debug(" %d ", counter); 99 | if(!(counter++%18)) 100 | debug("One second passed\n"); 101 | } 102 | -------------------------------------------------------------------------------- /kernel/cpu/isr.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | extern void isr0 (void); 11 | extern void isr1 (void); 12 | extern void isr2 (void); 13 | extern void isr3 (void); 14 | extern void isr4 (void); 15 | extern void isr5 (void); 16 | extern void isr6 (void); 17 | extern void isr7 (void); 18 | extern void isr8 (void); 19 | extern void isr9 (void); 20 | extern void isr10(void); 21 | extern void isr11(void); 22 | extern void isr12(void); 23 | extern void isr13(void); 24 | extern void isr14(void); 25 | extern void isr15(void); 26 | extern void isr16(void); 27 | extern void isr17(void); 28 | extern void isr18(void); 29 | extern void isr19(void); 30 | extern void isr20(void); 31 | extern void isr21(void); 32 | extern void isr22(void); 33 | extern void isr23(void); 34 | extern void isr24(void); 35 | extern void isr25(void); 36 | extern void isr26(void); 37 | extern void isr27(void); 38 | extern void isr28(void); 39 | extern void isr29(void); 40 | extern void isr30(void); 41 | extern void isr31(void); 42 | extern void isr128(void); 43 | 44 | 45 | #define SAVE_PROCESS_STATE \ 46 | {\ 47 | current_process->stat.rax = regs->rax;\ 48 | current_process->stat.rdx = regs->rdx;\ 49 | current_process->stat.rcx = regs->rcx;\ 50 | current_process->stat.rbx = regs->rbx;\ 51 | current_process->stat.rsp = regs->rsp;\ 52 | current_process->stat.rbp = regs->rbp;\ 53 | current_process->stat.rsi = regs->rsi;\ 54 | current_process->stat.rdi = regs->rdi;\ 55 | current_process->stat.r8 = regs->r8;\ 56 | current_process->stat.r9 = regs->r9;\ 57 | current_process->stat.r10 = regs->r10;\ 58 | current_process->stat.r11 = regs->r11;\ 59 | current_process->stat.r12 = regs->r12;\ 60 | current_process->stat.r13 = regs->r13;\ 61 | current_process->stat.r14 = regs->r14;\ 62 | current_process->stat.r15 = regs->r15;\ 63 | current_process->stat.rip = regs->rip;\ 64 | current_process->stat.rflags = regs->rflags;\ 65 | } 66 | 67 | regs_t r; 68 | 69 | void syscall_int(regs_t *regs) 70 | { 71 | /* NOTE : This memcpy can be optimized if we assume strict following of 72 | GCC calling conventions and store only registers that shouldn't change. 73 | */ 74 | memcpy(¤t_process->stat, regs, sizeof(regs_t)); 75 | 76 | /* 77 | current_process->stat.rax = regs->rax; 78 | current_process->stat.rdx = regs->rdx; 79 | current_process->stat.rcx = regs->rcx; 80 | current_process->stat.rbx = regs->rbx; 81 | current_process->stat.rsp = regs->rsp; 82 | current_process->stat.rbp = regs->rbp; 83 | current_process->stat.rsi = regs->rsi; 84 | current_process->stat.rdi = regs->rdi; 85 | current_process->stat.r8 = regs->r8; 86 | current_process->stat.r9 = regs->r9; 87 | current_process->stat.r10 = regs->r10; 88 | current_process->stat.r11 = regs->r11; 89 | current_process->stat.r12 = regs->r12; 90 | current_process->stat.r13 = regs->r13; 91 | current_process->stat.r14 = regs->r14; 92 | current_process->stat.r15 = regs->r15; 93 | current_process->stat.rip = regs->rip; 94 | current_process->stat.rflags = regs->rflags; 95 | */ 96 | void (*f)(uint64_t, uint64_t, uint64_t) = sys_calls[regs->rax]; 97 | f(regs->rbx, regs->rcx, regs->rdx); 98 | return; 99 | /*uint8_t *str = msg; 100 | uint8_t *v = (uint8_t*)0xFFFFFFFFC00B8000; 101 | while(*str) 102 | { 103 | *v = *str++; 104 | v += 2; 105 | }*/ 106 | } 107 | 108 | 109 | static const char *msg[32] = { 110 | "Division by zero", /* 0 */ 111 | "Debug", 112 | "Non-maskable interrupt", 113 | "Breakpoint", 114 | "Detected overflow", 115 | "Out-of-bounds", /* 5 */ 116 | "Invalid opcode", 117 | "No coprocessor", 118 | "Double fault", 119 | "Coprocessor segment overrun", 120 | "Bad TSS", /* 10 */ 121 | "Segment not present", 122 | "Stack fault", 123 | "General protection fault", 124 | "Page fault", 125 | "Unknown interrupt", /* 15 */ 126 | "Coprocessor fault", 127 | "Alignment check", 128 | "Machine check", 129 | "Reserved", 130 | "Reserved", 131 | "Reserved", 132 | "Reserved", 133 | "Reserved", 134 | "Reserved", 135 | "Reserved", 136 | "Reserved", 137 | "Reserved", 138 | "Reserved", 139 | "Reserved", 140 | "Reserved", 141 | "Reserved" 142 | }; 143 | 144 | uint32_t fork_skip_page = 0; 145 | void interrupt(regs_t *regs) 146 | { 147 | extern uint64_t int_num; 148 | extern uint64_t err_num; 149 | debug("rip -> %lx\n", regs->rip); 150 | debug("Recieved interrupt [%d] [%x] : %s\n", (uint32_t)int_num, err_num, msg[int_num]); 151 | 152 | #if _LAZYALLOC_ 153 | if(int_num == 14) // Page fault 154 | { 155 | uint64_t addr; 156 | asm("mov %%cr2, %%rax; movq %%rax, %0;"::"g"(addr)); 157 | if(forking || addr <= current_process->size * 0x1000 158 | && addr >= current_process->addr 159 | && regs->rip <= current_process->size * 0x1000 160 | && regs->rip >= current_process->addr 161 | ) 162 | { 163 | if(forking) 164 | { 165 | debug("forking hack %lx\n", regs->r10); 166 | fork_skip_page = 1; 167 | regs->rip = regs->r10; 168 | return; 169 | } 170 | debug("Lazy alloc %lx\n", addr); 171 | map_mem_user(current_process->pdpt, (uint64_t*)(addr/0x1000*0x1000), 0x1000); 172 | kernel_idle(); 173 | } 174 | } 175 | #endif 176 | 177 | #if 1 178 | if(regs->rip == -1) // Returned from signal handler 179 | { 180 | void *stack = (void*)regs->rsp; 181 | memcpy(¤t_process->stat, stack, sizeof(stat_t)); 182 | debug("%lx\n", current_process->stat.rip); 183 | kernel_idle(); 184 | } 185 | if(regs->rip < 0x7FC0000000) // exception generated by user process 186 | { 187 | switch((uint32_t)int_num) 188 | { 189 | case 0: 190 | signal_send(current_process, SIGFPE); 191 | break; 192 | case 6: 193 | case 7: 194 | if(fpu_state) 195 | { 196 | signal_send(current_process, SIGILL); 197 | break; 198 | } 199 | trap_fpu(); 200 | kernel_idle(); 201 | break; 202 | case 13: 203 | case 14: 204 | signal_send(current_process, SIGSEGV); 205 | break; 206 | case 16: 207 | signal_send(current_process, SIGFPE); 208 | break; 209 | default: 210 | signal_send(current_process, SIGILL); 211 | break; 212 | } 213 | kernel_idle(); 214 | } 215 | #endif 216 | //dump_stack(); 217 | debug("Kernel exception\n"); // That's bad 218 | for(;;); 219 | } 220 | 221 | void isr_install(void) { 222 | idt_set_gate(0x00, isr0, 0x08, 0x8E); 223 | idt_set_gate(0x01, isr1, 0x08, 0x8E); 224 | idt_set_gate(0x02, isr2, 0x08, 0x8E); 225 | idt_set_gate(0x03, isr3, 0x08, 0x8E); 226 | idt_set_gate(0x04, isr4, 0x08, 0x8E); 227 | idt_set_gate(0x05, isr5, 0x08, 0x8E); 228 | idt_set_gate(0x06, isr6, 0x08, 0x8E); 229 | idt_set_gate(0x07, isr7, 0x08, 0x8E); 230 | idt_set_gate(0x08, isr8, 0x08, 0x8E); 231 | idt_set_gate(0x09, isr9, 0x08, 0x8E); 232 | idt_set_gate(0x0A, isr10, 0x08, 0x8E); 233 | idt_set_gate(0x0B, isr11, 0x08, 0x8E); 234 | idt_set_gate(0x0C, isr12, 0x08, 0x8E); 235 | idt_set_gate(0x0D, isr13, 0x08, 0x8E); 236 | idt_set_gate(0x0E, isr14, 0x08, 0x8E); 237 | idt_set_gate(0x0F, isr15, 0x08, 0x8E); 238 | idt_set_gate(0x10, isr16, 0x08, 0x8E); 239 | idt_set_gate(0x11, isr17, 0x08, 0x8E); 240 | idt_set_gate(0x12, isr18, 0x08, 0x8E); 241 | idt_set_gate(0x13, isr19, 0x08, 0x8E); 242 | idt_set_gate(0x14, isr20, 0x08, 0x8E); 243 | idt_set_gate(0x15, isr21, 0x08, 0x8E); 244 | idt_set_gate(0x16, isr22, 0x08, 0x8E); 245 | idt_set_gate(0x17, isr23, 0x08, 0x8E); 246 | idt_set_gate(0x18, isr24, 0x08, 0x8E); 247 | idt_set_gate(0x19, isr25, 0x08, 0x8E); 248 | idt_set_gate(0x1A, isr26, 0x08, 0x8E); 249 | idt_set_gate(0x1B, isr27, 0x08, 0x8E); 250 | idt_set_gate(0x1C, isr28, 0x08, 0x8E); 251 | idt_set_gate(0x1D, isr29, 0x08, 0x8E); 252 | idt_set_gate(0x1E, isr30, 0x08, 0x8E); 253 | idt_set_gate(0x1F, isr31, 0x08, 0x8E); 254 | idt_set_gate(0x80, isr128, 0x08, 0xEE); 255 | } 256 | -------------------------------------------------------------------------------- /kernel/devices/Makefile: -------------------------------------------------------------------------------- 1 | 2 | include ../Makefile.cfg 3 | 4 | OBJ = fpu.o pit.o ramdev.o ttydev.o console.o kbd.o ata.o devman.o 5 | OUT=../obj 6 | 7 | CFLAGS = -c -I ../include/ -mcmodel=large -nostdlib -ffreestanding 8 | 9 | all: $(OBJ) 10 | ${CP} $(OBJ) $(OUT) 11 | 12 | $(OUT)/%.o: %.c 13 | $(CC) $(CFLAGS) $< -o $@ 14 | 15 | clean: 16 | ${RM} -f $(OBJ) 17 | -------------------------------------------------------------------------------- /kernel/devices/ata.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #define MBR_TYPE_UNUSED 0x00 9 | #define MBR_BOOT_SIGNATURE 0xAA55 10 | 11 | #pragma pack(1) 12 | 13 | typedef struct { 14 | uint8_t status; 15 | struct { 16 | uint8_t h; 17 | uint16_t cs; 18 | } start_chs; 19 | uint8_t type; 20 | struct { 21 | uint8_t h; 22 | uint16_t cs; 23 | } end_chs; 24 | uint32_t start_lba; 25 | uint32_t sectors_count; 26 | } partition_t; 27 | 28 | typedef struct { 29 | uint8_t bootloader[440]; // Actual Bootloader code 30 | uint32_t disk_signiture; 31 | uint16_t copy_protected; 32 | partition_t ptab[4]; // Partition table 33 | uint16_t boot_signature; 34 | } mbr_t; 35 | 36 | #pragma pack() 37 | 38 | mbr_t * read_mbr(inode_t *inode) 39 | { 40 | static mbr_t mbr; 41 | if(inode->fs->read(inode, 0, sizeof(mbr_t), (void*)&mbr) != sizeof(mbr_t)) 42 | return NULL; 43 | 44 | if(mbr.boot_signature != MBR_BOOT_SIGNATURE) 45 | return NULL; 46 | 47 | return &mbr; 48 | } 49 | 50 | 51 | static uint32_t ata_probe(inode_t *inode) 52 | { 53 | // XXX : Seriously !? ... do you call this a driver !? 54 | static inode_t sda_inode = 55 | (inode_t) 56 | { 57 | .name = "sda", 58 | .type = FS_BLKDEV, 59 | .fs = &devfs, 60 | .dev = &atadev, 61 | .p = NULL, 62 | }; 63 | vfs_create(inode, "/", &sda_inode); 64 | 65 | mbr_t *mbr_p = read_mbr(&sda_inode); 66 | 67 | mbr_t mbr = *mbr_p; 68 | int i; 69 | for(i = 0; i < 4; ++i){ 70 | if(mbr.ptab[i].type == MBR_TYPE_UNUSED){ 71 | continue; 72 | } 73 | atadev_private_t *p = kmalloc(sizeof(*p)); 74 | *p = (atadev_private_t) 75 | { 76 | .start_lba = mbr.ptab[i].start_lba, 77 | .end_lba = mbr.ptab[i].start_lba + mbr.ptab[i].sectors_count - 1, 78 | }; 79 | 80 | char *_name = "sda "; 81 | _name[3] = "1234"[i]; 82 | 83 | inode_t *n = kmalloc(sizeof(*n)); 84 | *n = (inode_t) 85 | { 86 | .name = strdup(_name), 87 | .type = FS_BLKDEV, 88 | .fs = &devfs, 89 | .dev = &atadev, 90 | .p = p, 91 | }; 92 | vfs_create(inode, "/", n); 93 | } 94 | } 95 | 96 | void ata_wait() 97 | { 98 | inb(ATA_CMD); 99 | inb(ATA_CMD); 100 | inb(ATA_CMD); 101 | inb(ATA_CMD); 102 | } 103 | 104 | void ata_read_sectors(uint32_t LBA, uint8_t sectors, void *buf) 105 | { 106 | asm("pushfq"); // Storing rflags register 107 | outb(ATA_LBA3, 0xFF & ( (LBA >> 24) | ATA_DRV0 | ATA_LBA_MODE) ); 108 | outb(0x1F1, 0); // Wait !! 109 | outb(ATA_SECT, sectors); 110 | outb(ATA_LBA0, 0xFF & ( LBA >> 0 ) ); 111 | outb(ATA_LBA1, 0xFF & ( LBA >> 8 ) ); 112 | outb(ATA_LBA2, 0xFF & ( LBA >> 16 ) ); 113 | 114 | outb(ATA_CMD, 0xFF & ATA_READ); 115 | 116 | uint8_t *_buf = buf; 117 | _buf -= 512; 118 | while(sectors--) 119 | { 120 | ata_wait(); 121 | uint8_t status; 122 | do status = inb(ATA_CMD); 123 | while( (status & 0x80) || !(status & 0x8)); // Wait until buffer is ready 124 | 125 | asm("movq %0, %%rdi; rep insw;" 126 | : 127 | :"g"( _buf += 512 ), "c"(256), "d"(ATA_DATA) 128 | :"rdi" 129 | ); 130 | } 131 | 132 | //debug("buf %lx\n", *(uint64_t*)buf); 133 | asm("popfq"); // Restoring rflags register 134 | } 135 | 136 | static uint32_t 137 | ata_read(inode_t *inode, uint64_t addr, uint64_t size, void *buf) 138 | { 139 | debug("read %lx, %lx, %lx\n", addr, size, buf); 140 | /* TODO : Try to optimize this by doing some math 141 | instead of being dumb and copying the contents */ 142 | 143 | if(inode && inode->p) // Partition !? 144 | { 145 | atadev_private_t *p = inode->p; 146 | return ata_read(NULL, p->start_lba * 512 + addr, size, buf); 147 | } 148 | 149 | uint32_t LBA = addr/512; 150 | uint32_t offset = addr - 512 * LBA; 151 | uint32_t sectors = size/512 + + (size%512?1:0); 152 | uint8_t *_buf = kmalloc(512 * sectors); 153 | ata_read_sectors(LBA, sectors, _buf); 154 | memcpy(buf, _buf + offset, size); 155 | kfree(_buf); 156 | debug("ret\n"); 157 | return size; 158 | } 159 | 160 | // TODO : this ata_write won't work because it's too fast 161 | void ata_write(uint32_t LBA, uint8_t sectors, void *buf) 162 | { 163 | asm("pushfq"); // Storing rflags register 164 | outb(ATA_LBA3, 0xFF & ( (LBA >> 24) | ATA_DRV0 | ATA_LBA_MODE) ); 165 | outb(ATA_SECT, sectors); 166 | outb(ATA_LBA0, 0xFF & ( LBA >> 0 ) ); 167 | outb(ATA_LBA1, 0xFF & ( LBA >> 8 ) ); 168 | outb(ATA_LBA2, 0xFF & ( LBA >> 16 ) ); 169 | 170 | outb(ATA_CMD, 0xFF & ATA_WRITE); 171 | ata_wait(); 172 | while(!(inb(ATA_CMD)&8)); // Wait until buffer is ready 173 | asm("movq %0, %%rsi; rep outsw;" 174 | : 175 | :"g"(buf), "c"(256 * sectors), "d"(ATA_DATA) 176 | :"rsi" 177 | ); 178 | asm("popfq"); // Restoring rflags register 179 | } 180 | 181 | dev_t atadev = 182 | { 183 | .name = "ATA", 184 | .probe = &ata_probe, 185 | .read = &ata_read, 186 | }; 187 | -------------------------------------------------------------------------------- /kernel/devices/console.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | static uint32_t 10 | console_ioctl(inode_t *inode_unused, uint64_t request, va_list args) 11 | { 12 | switch(request) 13 | { 14 | case 0: // Draw Character (x, y, chr, fg, bg) 15 | { 16 | uint32_t posx = va_arg(args, uint32_t); 17 | uint32_t posy = va_arg(args, uint32_t); 18 | uint32_t chr = va_arg(args, uint32_t); 19 | uint32_t fg = va_arg(args, uint32_t); 20 | uint32_t bg = va_arg(args, uint32_t); 21 | uint32_t pos = 2 * (posx + posy * 80); 22 | //debug("Drawing at %d %d\n", posx, posy); 23 | *(uint8_t*)((uint64_t)&VMA + 0xB8000 + pos++) = chr & 0xFF; 24 | *(uint8_t*)((uint64_t)&VMA + 0xB8000 + pos++) = fg & 0xF | ((bg << 4) & 0xF0); 25 | } 26 | break; 27 | case 1: // Set cursor (pos) NOTE: pos = x + y * tty->cols 28 | { 29 | uint32_t pos = va_arg(args, uint32_t); 30 | //debug("Set Cur %d\n", pos); 31 | outb(0x3D4, 0x0F); 32 | outb(0x3D5, (uint8_t)(pos & 0xFF)); 33 | 34 | outb(0x3D4, 0x0E); 35 | outb(0x3D5, (uint8_t)((pos >> 8) & 0xFF)); 36 | } 37 | break; 38 | } 39 | } 40 | 41 | static uint32_t 42 | console_probe(inode_t *inode) 43 | { 44 | static inode_t console_inode = 45 | (inode_t) 46 | { 47 | .name = "console", 48 | .type = FS_CHRDEV, 49 | .dev = &condev, 50 | .fs = &devfs, 51 | }; 52 | vfs_create(inode, "/", &console_inode); 53 | } 54 | 55 | static void 56 | virtcon_draw(virtcon_device_t *virtcon) 57 | { 58 | //XXX temp draw 59 | uint8_t *vmem = (uint8_t*)((uint64_t)&VMA + 0xB8000); 60 | uint32_t i; 61 | for(i = 0; i < 80*25; ++i) 62 | { 63 | vmem[2 * i + 0] = virtcon->buf[3*i]; 64 | vmem[2 * i + 1] = 0xFF & (virtcon->buf[3*i+1] | virtcon->buf[3*i+2] << 4); 65 | } 66 | } 67 | 68 | static void 69 | virtcon_putc(virtcon_device_t *virtcon, uint8_t chr, 70 | uint32_t x, uint32_t y, uint32_t fg, uint32_t bg) 71 | { 72 | if(x > virtcon->w || y > virtcon->h) return; 73 | uint32_t pos = 3 * (y * virtcon->w + x); 74 | virtcon->buf[ pos] = chr; 75 | virtcon->buf[++pos] = fg; 76 | virtcon->buf[++pos] = bg; 77 | } 78 | 79 | static void 80 | virtcon_puts(virtcon_device_t *virtcon, uint8_t *str, uint32_t size, 81 | uint32_t x, uint32_t y, uint32_t fg, uint32_t bg) 82 | { 83 | if(!size) return; 84 | uint32_t pos = 3 * (y * virtcon->w + x) - 1; 85 | uint32_t i; 86 | for(i = 0; i < size; ++i) 87 | { 88 | virtcon->buf[++pos] = str[i]; 89 | virtcon->buf[++pos] = fg; 90 | virtcon->buf[++pos] = bg; 91 | //virtcon_putc(virtcon, str[i], i%virtcon->w, i/virtcon->w, fg, bg); 92 | } 93 | } 94 | 95 | static void 96 | virtcon_setcur(virtcon_device_t *virtcon, uint32_t c, uint32_t r) 97 | { 98 | if(c > virtcon->w || r > virtcon->h) return; 99 | 100 | uint32_t pos = r * virtcon->w + c; 101 | if(!virtcon->buf[3 * pos + 1]) 102 | virtcon->buf[3 * pos + 1] = 0x7; 103 | 104 | outb(0x3D4, 0x0F); 105 | outb(0x3D5, (uint8_t)(pos & 0xFF)); 106 | outb(0x3D4, 0x0E); 107 | outb(0x3D5, (uint8_t)((pos >> 8) & 0xFF)); 108 | } 109 | 110 | static void 111 | virtcon_scroll(virtcon_device_t *virtcon, uint32_t n) 112 | { 113 | uint32_t to_copy = (virtcon->h - n) * virtcon->w * 3; 114 | memcpy(virtcon->buf, virtcon->buf + 3 * n * virtcon->w, to_copy); 115 | 116 | memset(virtcon->buf + to_copy, 0, 3 * n * virtcon->w); 117 | } 118 | 119 | virtcon_device_t * 120 | get_virtcon(tty_device_t *tty, uint32_t w, uint32_t h) 121 | { 122 | virtcon_device_t *virtcon = kmalloc(sizeof(virtcon_device_t)); 123 | virtcon->buf = kmalloc(h * w * 3); // chr | fg | bg 124 | memset(virtcon->buf, 0, h * w * 3); 125 | virtcon->putc = &virtcon_putc; 126 | virtcon->puts = &virtcon_puts; 127 | virtcon->setcur = &virtcon_setcur; 128 | virtcon->scroll = &virtcon_scroll; 129 | virtcon->draw = &virtcon_draw; 130 | virtcon->w = w; 131 | virtcon->h = h; 132 | return virtcon; 133 | } 134 | 135 | dev_t condev = 136 | (dev_t) 137 | { 138 | .name = "console", 139 | .probe = console_probe, 140 | .read = NULL, 141 | .write = NULL, 142 | .ioctl = console_ioctl, 143 | }; 144 | -------------------------------------------------------------------------------- /kernel/devices/devman.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | dev_t * devices[] = 9 | { 10 | &condev, /* Virtual Console driver */ 11 | &ttydev, /* TTY driver */ 12 | &atadev, 13 | NULL, 14 | }; 15 | 16 | static void devman_init(void) 17 | { 18 | debug("Loading device drivers "); 19 | dev_t **dev = devices; 20 | 21 | while(*dev) 22 | { 23 | (*dev)->probe(&dev_root); 24 | ++dev; 25 | debug("."); 26 | } 27 | 28 | debug(" [done]\n"); 29 | 30 | vfs_mount(vfs_root, "/dev", &dev_root); 31 | } 32 | 33 | devman_t devman = 34 | { 35 | .init = devman_init, 36 | }; 37 | -------------------------------------------------------------------------------- /kernel/devices/fpu.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | process_t *last_fpu_proc = NULL; // The last process that used the FPU 8 | uint8_t fpu_state = 0; 9 | 10 | uint8_t fstat[512] __attribute__((aligned(16))); 11 | 12 | void save_fpu() 13 | { 14 | debug("Saving FPU [%s]\n", current_process->name); 15 | asm("fxsave %0"::"m"(fstat)); 16 | memcpy(current_process->fstat, &fstat, 512); 17 | } 18 | 19 | void restore_fpu() 20 | { 21 | debug("Restoring FPU [%s]\n", current_process->name); 22 | memcpy(&fstat, current_process->fstat, 512); 23 | asm("fxrstor %0"::"m"(fstat)); 24 | } 25 | 26 | void trap_fpu() 27 | { 28 | debug("Traping FPU [%s]\n", current_process->name); 29 | enable_fpu(); 30 | if(last_fpu_proc == current_process) 31 | return; 32 | 33 | last_fpu_proc = current_process; 34 | if(!current_process->fstat) 35 | { 36 | asm("fninit;"); 37 | current_process->fstat = kmalloc(512); 38 | return; 39 | } 40 | 41 | restore_fpu(); 42 | } 43 | 44 | void enable_fpu() 45 | { 46 | if(fpu_state) return; 47 | fpu_state = 1; 48 | //debug("Enabling FPU [%s]\n", current_process->name); 49 | /* Enable SSE */ 50 | /* Sets CR4.OSFXSR & CR4.OSXMMEXCPT */ 51 | asm("clts; \ 52 | movq %cr4, %rax; \ 53 | or $0x600, %rax; \ 54 | movq %rax, %cr4;" 55 | ); 56 | } 57 | 58 | void disable_fpu() 59 | { 60 | if(!fpu_state) return; 61 | fpu_state = 0; 62 | debug("Disabling FPU [%s]\n", current_process->name); 63 | /* Disable all FPU & SSE instructions */ 64 | /* Sets CR0.EM ( Emulation bit ) so all FPU instructions trap to kernel */ 65 | asm("movq %cr0, %rax; \ 66 | and $~0x4, %rax; \ 67 | movq %rax, %cr0;" 68 | ); 69 | } 70 | -------------------------------------------------------------------------------- /kernel/devices/kbd.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | uint32_t pos = 0; 7 | 8 | void kbd_wait(void) 9 | { 10 | while(inb(0x64) & 2); 11 | } 12 | 13 | uint32_t spec = 0; 14 | 15 | void kbd_handler(regs_t *r) 16 | { 17 | kbd_wait(); 18 | uint8_t scancode = inb(0x60); 19 | if(scancode == 0xE0) 20 | { 21 | spec = 1; 22 | return; 23 | } 24 | /* 25 | static inode_t *i; 26 | if(!i) i = vfs_trace_path(vfs_root, "/dev/console"); 27 | if(spec) 28 | { 29 | switch(scancode) 30 | { 31 | case 0x4D: ++pos; break; 32 | case 0x4B: --pos; break; 33 | } 34 | spec = 0; 35 | } 36 | 37 | i->fs->ioctl(i, 1, pos); 38 | */ 39 | extern void tty_kbd(uint8_t); 40 | tty_kbd(scancode); 41 | } 42 | 43 | -------------------------------------------------------------------------------- /kernel/devices/mouse.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #define MOUSE_CMD 0x64 6 | #define MOUSE_DATA 0x60 7 | #define SEND_CMD 0xD4 // Sent to port 0x64 to indicate that command will be sent to port 0x60 8 | #define ENABLE_AUX_PS2 0xA8 9 | #define GET_COMPAQ_STATUS 0x20 10 | #define SET_COMPAQ_STATUS 0x60 11 | #define USE_DEFAULTS 0xF6 12 | #define ENABLE_MOUSE 0xF4 13 | 14 | 15 | void mouse_wait(uint32_t i) 16 | { 17 | if(!i) 18 | while(!(inb(MOUSE_CMD)&1)); 19 | else 20 | while(inb(MOUSE_CMD)&2); 21 | } 22 | 23 | uint8_t mouse_read() 24 | { 25 | mouse_wait(0); 26 | return inb(0x60); 27 | } 28 | 29 | void mouse_write(uint8_t chr) 30 | { 31 | mouse_wait(1); 32 | outb(MOUSE_CMD, SEND_CMD); 33 | mouse_wait(1); 34 | outb(MOUSE_DATA, chr); 35 | } 36 | 37 | void mouse_init() 38 | { 39 | mouse_wait(1); 40 | outb(MOUSE_CMD, ENABLE_AUX_PS2); 41 | 42 | mouse_wait(1); 43 | outb(MOUSE_CMD, GET_COMPAQ_STATUS); 44 | uint8_t status = mouse_read() | 2; // Enable IRQ12 45 | 46 | mouse_wait(1); 47 | outb(MOUSE_CMD, SET_COMPAQ_STATUS); 48 | 49 | mouse_wait(0); 50 | outb(MOUSE_DATA, status); 51 | 52 | mouse_write(USE_DEFAULTS); 53 | mouse_read(); // Waits for ACK 54 | 55 | mouse_write(ENABLE_MOUSE); 56 | mouse_read(); 57 | } 58 | 59 | typedef struct 60 | { 61 | uint8_t left : 1; 62 | uint8_t right : 1; 63 | uint8_t mid : 1; 64 | uint8_t _1 : 1; 65 | uint8_t x_sign : 1; 66 | uint8_t y_sign : 1; 67 | uint8_t x_over : 1; 68 | uint8_t y_over : 1; 69 | } __attribute__((packed)) mouse_packet_t; 70 | 71 | uint32_t posx = 0; 72 | uint32_t posy = 0; 73 | 74 | void mouse_handler(regs_t *regs) 75 | { 76 | static uint8_t cycle = 0; 77 | static uint8_t mouse_data[3]; 78 | mouse_data[cycle++] = inb(MOUSE_DATA); 79 | if(cycle == 3) 80 | { 81 | cycle = 0; // We are done .. reset 82 | mouse_packet_t *packet = (mouse_packet_t*)&mouse_data[0]; 83 | 84 | if(packet->x_over || packet->y_over) return; 85 | 86 | posx += mouse_data[1]; 87 | posy += mouse_data[2]; 88 | 89 | extern void draw_char(uint8_t, uint32_t, uint32_t, uint32_t); 90 | //draw_char('A', posx * 3, posy * 3, -1); 91 | debug("dx:%d dy:%d\n", 0xFF & mouse_data[1], 0xFF & mouse_data[2]); 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /kernel/devices/pipedev.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | static inode_t * 6 | pipedev_load(inode_t *inode_unused) 7 | { 8 | 9 | } 10 | 11 | static uint32_t 12 | pipedev_read(inode_t *inode, uint64_t offset, uint64_t size, void *buf) 13 | { 14 | 15 | 16 | } 17 | -------------------------------------------------------------------------------- /kernel/devices/pit.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | uint32_t ticks = 0; 8 | uint32_t sub_ticks = 0; 9 | uint32_t pit_freq = 0; 10 | uint32_t sub_tick_us = 0; 11 | 12 | void pit_set_freq(uint32_t hz) 13 | { 14 | pit_freq = hz; 15 | sub_tick_us = 1000000/hz; 16 | 17 | outb(0x43, 0x36); 18 | uint32_t div = 1193180/hz; 19 | outb(0x40, div & 0xFF); 20 | outb(0x40, (div >> 8) & 0xFF); 21 | } 22 | 23 | void pit_irq_handler() 24 | { 25 | if(sub_ticks++ == pit_freq) 26 | { 27 | ticks++; 28 | sub_ticks = 0; 29 | } 30 | 31 | if(!(sub_ticks * sub_tick_us % (1000 * 18))) schedule(); 32 | } 33 | 34 | void pit_install() 35 | { 36 | irq_install_handler(0, pit_irq_handler); 37 | } 38 | 39 | -------------------------------------------------------------------------------- /kernel/devices/ramdev.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | static uint32_t 6 | ramdev_read(inode_t *inode, uint64_t offset, uint64_t size, void *_buf) 7 | { 8 | ramdev_private_t *p = inode->p; 9 | if(offset <= p->size) 10 | { 11 | uint32_t to_read = MIN(size, p->size - offset); 12 | memcpy(_buf, p->ptr, to_read); 13 | return to_read; 14 | } 15 | return -1; 16 | } 17 | 18 | static uint32_t 19 | ramdev_write(inode_t *inode, uint64_t offset, uint64_t size, void *_buf) 20 | { 21 | ramdev_private_t *p = inode->p; 22 | if(offset <= p->size) 23 | { 24 | uint32_t to_write = MIN(size, p->size - offset); 25 | memcpy(p->ptr, _buf, to_write); 26 | return to_write; 27 | } 28 | return -1; 29 | } 30 | 31 | dev_t ramdev = 32 | { 33 | .name = "ramdev", 34 | .type = DEV_CHR, 35 | .read = &ramdev_read, 36 | .write = &ramdev_write, 37 | }; 38 | -------------------------------------------------------------------------------- /kernel/devices/ttydev.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | static uint32_t tty_count = 0; 16 | inode_t *cur_tty; 17 | 18 | typedef struct 19 | { 20 | uint8_t *vmem; // Video Memory 21 | uint32_t cur_tty; // Currently active tty 22 | } tty_master_device_t; 23 | 24 | static void tty_load_master(void *ptr) 25 | {/* 26 | // inode_t *tty = kmalloc(sizeof(inode_t)); 27 | // ttym = tty; 28 | // tty->name = "ttym"; 29 | tty->type = FS_FILE; 30 | tty->fs = &devtty; 31 | tty_device_t *tmp = kmalloc(sizeof(tty_device_t)); 32 | tmp->is_master = 1; 33 | tty_master_device_t *tmp2 = kmalloc(sizeof(tty_master_device_t)); 34 | tmp2->vmem = ptr; 35 | tmp2->cur_tty = 0; 36 | tmp->master = tmp2; 37 | tty->p = tmp; 38 | vfs_create(vfs_root, "/dev/", tty); 39 | */ 40 | } 41 | 42 | void tty_switch(uint32_t tty_id) 43 | { 44 | /* uint8_t *tty_id_str = itoa(tty_id); 45 | uint8_t *tty_path = strcat("/dev/tty", tty_id_str); 46 | 47 | inode_t *inode = vfs_trace_path(vfs_root, tty_path); 48 | if(!inode) return; 49 | 50 | kfree(tty_id_str); kfree(tty_path); 51 | 52 | tty_device_t *tty = inode->p; 53 | tty->master->invoke(tty, TTYM_SWITCH); 54 | /* //((tty_master_t*)((tty_device_t*)ttym->p)->master)->cur_tty = tty; 55 | 56 | uint8_t *v = strcat("/dev/tty", (uint8_t*)itoa(tty)); 57 | inode_t *f = vfs_trace_path(vfs_root, v); 58 | 59 | uint8_t *vmem = ((tty_master_device_t*)((tty_device_t*)ttym->p)->master)->vmem; 60 | uint64_t i; 61 | for(i = 0; i < f->size; i+=2) 62 | vmem[i] = ((tty_device_t*)f->p)->ptr[i]; 63 | 64 | outb(0x3D4, 0x0F); 65 | outb(0x3D5, (uint8_t)((((tty_device_t*)f->p)->pos)/2 & 0xFF)); 66 | 67 | outb(0x3D4, 0x0E); 68 | outb(0x3D5, (uint8_t)((((tty_device_t*)f->p)->pos)/2 >> 8) & 0xFF); 69 | */ 70 | } 71 | 72 | static inode_t *tty_load(void *ptr) 73 | { 74 | /* inode_t *tty = kmalloc(sizeof(inode_t)); 75 | tty->name = strcat("tty", (uint8_t*)itoa(tty_count)); 76 | tty->type = FS_FILE; 77 | tty->fs = &devtty; 78 | tty_device_t *tmp = kmalloc(sizeof(tty_device_t)); 79 | 80 | tmp->is_master = 0; 81 | tmp->id = tty_count++; 82 | tmp->ptr = ptr; 83 | tmp->pos = 0; 84 | tmp->row = 0; 85 | tmp->col = 0; 86 | 87 | tty->p = tmp; 88 | tty->size = 25 * 80 * 2; 89 | vfs_create(vfs_root, "/dev/", tty); 90 | return tty; 91 | */ 92 | } 93 | 94 | 95 | #define VIRTCON_SIZE(virtcon) ((virtcon->w) * (virtcon->h)) 96 | #define DIV_ROUND_UP(val, div) ((val/div) + !!(val%div)); 97 | 98 | static void tty_scroll(tty_device_t *tty, uint32_t n) 99 | { 100 | /* uint32_t i = 0, j = n * tty->cols; 101 | uint8_t *ptr = tty->ptr; 102 | memcpy(tty->ptr, tty->ptr + n * tty->cols, VIRTCON_SIZE(virtcon) - n * tty->cols); 103 | */ 104 | } 105 | 106 | static uint32_t 107 | ttydev_probe(inode_t *inode) 108 | { 109 | static tty_master_t ttym; 110 | ttym = 111 | (tty_master_t) 112 | { 113 | .cur_tty = 0, 114 | //.invoke = ttym_invoke, 115 | .console = vfs_trace_path(inode, "/console"), 116 | }; 117 | 118 | #if _DBG_CON_ 119 | extern tty_device_t serial_tty_dev; 120 | static tty_device_t tty_dev; 121 | tty_dev = serial_tty_dev; 122 | tty_dev.master = &ttym; 123 | #else 124 | static tty_device_t tty_dev; 125 | tty_dev = 126 | (tty_device_t) 127 | { 128 | .id = 0, 129 | .master = &ttym, 130 | .pos = 0, 131 | .virtcon = get_virtcon(&tty_dev, 80, 25), 132 | .p = NULL, 133 | .buf = NULL, 134 | .len = 0, 135 | }; 136 | #endif 137 | 138 | static inode_t tty_inode = 139 | (inode_t) 140 | { 141 | .name = "0", 142 | .type = FS_CHRDEV, 143 | .fs = &devfs, 144 | .dev = &ttydev, 145 | .p = &tty_dev, 146 | }; 147 | 148 | static inode_t tty_dir = 149 | (inode_t) 150 | { 151 | .name = "tty", 152 | .type = FS_DIR, 153 | //.fs = &devfs, 154 | //.dev = &ramdev, 155 | }; 156 | 157 | cur_tty = &tty_inode; 158 | 159 | vfs_create(inode, "/", &tty_dir); 160 | vfs_create(&tty_dir, "/", &tty_inode); 161 | } 162 | 163 | static uint32_t 164 | ttydev_write(inode_t *inode, uint64_t offset_unused, uint64_t size, void *__buf) 165 | { 166 | uint8_t *_buf = __buf; 167 | tty_device_t *tty = inode->p; 168 | virtcon_device_t *virtcon = tty->virtcon; 169 | 170 | if((tty->pos + size) > VIRTCON_SIZE(virtcon)) 171 | { 172 | uint32_t lines_to_scroll = 173 | DIV_ROUND_UP(((tty->pos + size) - VIRTCON_SIZE(virtcon)), virtcon->w); 174 | virtcon->scroll(virtcon, lines_to_scroll); 175 | tty->pos -= lines_to_scroll * virtcon->w; 176 | } 177 | 178 | static uint32_t fg = 0x7, bg = 0, light = 0; 179 | uint32_t i = 0; 180 | uint32_t pos = 0; 181 | 182 | uint8_t *buf = kmalloc(size); 183 | memcpy(buf, _buf, size); 184 | 185 | while(i < size) 186 | { 187 | // Add special chararcters here 188 | while(i < size && buf[i] && !within(buf[i], "\n\b\033\t")) 189 | ++i; 190 | 191 | switch(buf[i]) 192 | { 193 | case '\033': 194 | buf[i] = '\0'; 195 | virtcon->puts( virtcon, 196 | &buf[pos], 197 | i - pos, // Size 198 | tty->pos % virtcon->w, // X 199 | tty->pos / virtcon->w, // Y 200 | fg, // fg colour 201 | bg // bg color 202 | ); 203 | tty->pos += i - pos; 204 | pos = ++i; 205 | { 206 | // Parsing the escape sequence 207 | switch(buf[i]) 208 | { 209 | // It'll get messy down there so we will drop `case' 210 | // indentation! 211 | 212 | case '[': 213 | { 214 | uint32_t k = i++; 215 | while(++k < size && buf[k] && !isalpha(buf[k])); 216 | if(buf[k]) 217 | switch(buf[k]) 218 | { 219 | case 'm': // Switch color 220 | { 221 | uint8_t fg_c[] = {0, 4, 2, 6, 1, 5, 3, 7}; 222 | uint32_t n = 0; 223 | while(i < k) 224 | { 225 | while(isdigit(buf[i])) 226 | n = 10 * n + buf[i++] - '0'; 227 | 228 | if(n == 0) 229 | { 230 | fg = 0x7; 231 | bg = 0x0; 232 | } else 233 | if(n == 1) 234 | { 235 | fg |= 0x8; 236 | } else 237 | if(n == 2) 238 | { 239 | fg &= ~0x8; 240 | } else 241 | if(n >= 30 && n <= 37) 242 | { 243 | fg = fg & ~0x7 | fg_c[n - 30]; 244 | } else 245 | if(n >= 90 && n <= 97) 246 | { 247 | fg = 0x8 | fg & ~0x7 | fg_c[n - 90]; 248 | } else 249 | if(n >= 40 && n <= 47) 250 | { 251 | bg = bg & ~0x7 | fg_c[n - 40]; 252 | } 253 | if(buf[i] != ';') break; 254 | ++i; 255 | n = 0; 256 | } 257 | pos = ++i; 258 | } 259 | break; 260 | 261 | case 'H': 262 | { 263 | if(i == k) 264 | { 265 | virtcon->setcur(virtcon, 0, 0); 266 | tty->pos = 0; 267 | pos = ++i; 268 | break; 269 | } 270 | 271 | uint32_t c = 0, r = 0; 272 | while(isdigit(buf[i])) 273 | r = 10 * r + buf[i++] - '0'; 274 | 275 | if(buf[i] != ';' && buf[i] != 'H') 276 | goto _default; 277 | 278 | ++i; 279 | while(isdigit(buf[i])) 280 | c = 10 * c + buf[i++] - '0'; 281 | 282 | if(buf[i] != 'H') goto _default; 283 | --c; --r; 284 | virtcon->setcur(virtcon, c, r); 285 | tty->pos = r * virtcon->w + c; 286 | pos = ++i; 287 | } 288 | break; 289 | 290 | case 'J': 291 | { 292 | // Now we only support 2J ( Erase all ) 293 | if(i == k) 294 | { 295 | // Ignored 296 | break; 297 | } 298 | 299 | uint32_t n = 0; 300 | while(isdigit(buf[i])) 301 | n = 10 * n + buf[i++] - '0'; 302 | 303 | if(buf[i] != 'J') goto _default; 304 | if(n == 2) 305 | { 306 | uint32_t r = 0; 307 | char __buf[virtcon->w]; 308 | memset(__buf, ' ', virtcon->w); 309 | 310 | while(r < virtcon->h) 311 | virtcon->puts( 312 | virtcon, 313 | __buf, 314 | virtcon->w, 315 | 0, 316 | r++, 317 | fg, 318 | bg 319 | ); 320 | pos = ++i; 321 | } 322 | } 323 | break; 324 | } 325 | } 326 | default: 327 | _default: 328 | --i; 329 | break; 330 | } 331 | } 332 | break; 333 | 334 | case '\t': 335 | buf[i] = '\0'; 336 | 337 | virtcon->puts( virtcon, 338 | &buf[pos], 339 | i - pos, // Size 340 | tty->pos % virtcon->w, // X 341 | tty->pos / virtcon->w, // Y 342 | fg, // fg colour 343 | bg // bg color 344 | ); 345 | 346 | tty->pos += i - pos + 4; 347 | pos = ++i; 348 | break; 349 | 350 | case '\n': 351 | buf[i] = '\0'; 352 | if(tty->pos + virtcon->w >= VIRTCON_SIZE(virtcon)) 353 | { 354 | virtcon->scroll(virtcon, 1); 355 | tty->pos -= virtcon->w; 356 | } 357 | 358 | virtcon->puts( virtcon, 359 | &buf[pos], 360 | i - pos, // Size 361 | tty->pos % virtcon->w, // X 362 | tty->pos / virtcon->w, // Y 363 | fg, // fg colour 364 | bg // bg color 365 | ); 366 | 367 | tty->pos += virtcon->w - tty->pos % virtcon->w; 368 | pos = ++i; 369 | break; 370 | 371 | case '\b': 372 | buf[i] = '\0'; 373 | virtcon->puts( virtcon, 374 | &buf[pos], 375 | i - pos, // Size 376 | tty->pos % virtcon->w, // X 377 | tty->pos / virtcon->w, // Y 378 | fg, // fg colour 379 | bg // bg color 380 | ); 381 | 382 | tty->pos += i - pos - 1; 383 | 384 | virtcon->putc( virtcon, 385 | '\0', 386 | tty->pos % virtcon->w, // X 387 | tty->pos / virtcon->w, // Y 388 | fg, // fg colour 389 | bg // bg color 390 | ); 391 | pos = ++i; 392 | break; 393 | 394 | default: 395 | virtcon->puts( virtcon, 396 | &buf[pos], 397 | i - pos, // Size 398 | tty->pos % virtcon->w, // X 399 | tty->pos / virtcon->w, // Y 400 | fg, // fg colour 401 | bg // bg color 402 | ); 403 | tty->pos += i - pos; 404 | pos = ++i; 405 | } 406 | } 407 | 408 | done: 409 | virtcon->setcur(virtcon, tty->pos%virtcon->w, tty->pos/virtcon->w); 410 | virtcon->draw(virtcon); 411 | return size; 412 | } 413 | 414 | 415 | #define ESC 0x01 416 | #define LSHIFT 0x2A 417 | #define _LSHIFT 0xAA 418 | #define RSHIFT 0x36 419 | #define _RSHIFT 0xB6 420 | #define CAPS 0x3A 421 | #define _CAPS 0xBA 422 | #define LALT 0x38 423 | #define _LALT 0xB8 424 | #define LCTL 0x1D 425 | #define _LCTL 0x9D 426 | #define F1 0x3B 427 | 428 | uint8_t kbd_us[] = 429 | { 430 | '\0', ESC, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=', '\b', 431 | '\t', 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']', '\n', 432 | '\0', 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', '\'', 433 | '\0', '\0', '\\', 'z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '/', 434 | '\0', '\0', '\0', ' ', 435 | }; 436 | 437 | uint8_t kbd_us_shift[] = 438 | { 439 | '\0', ESC, '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '_', '+', '\b', 440 | '\t', 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P', '{', '}', '\n', 441 | '\0', 'A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', '\"', 442 | '\0', '\0', '|', 'Z', 'X', 'C', 'V', 'B', 'N', 'M', '<', '>', '?', 443 | }; 444 | 445 | static uint8_t shift = 0, alt = 0, ctl = 0; 446 | static uint8_t flush = 0; 447 | //static uint8_t *_buf; 448 | static uint32_t i = 0; 449 | //static uint32_t _len = 0; 450 | //static process_t *p; 451 | 452 | void tty_kbd(uint8_t scancode) 453 | { 454 | 455 | tty_device_t *tty = cur_tty->p; 456 | 457 | uint64_t cur_pdpt = 0; 458 | if(tty->p) cur_pdpt = switch_pdpt(tty->p->pdpt); 459 | 460 | if(scancode == LSHIFT || scancode == RSHIFT) { shift = 1; goto done; } 461 | if(scancode == _LSHIFT || scancode == _RSHIFT) { shift = 0; goto done; } 462 | if(scancode == CAPS) { shift = !shift; goto done; } 463 | 464 | if(scancode == LALT) { alt = 1; goto done; } 465 | if(scancode == _LALT) { alt = 0; goto done; } 466 | if(scancode == LCTL) { ctl = 1; goto done; } 467 | if(scancode == _LCTL) { ctl = 0; goto done; } 468 | 469 | /* extern void tty_switch(uint32_t); 470 | 471 | // Special keys 472 | if(alt && scancode == ESC) 473 | { 474 | tty_switch(0); 475 | goto done; 476 | } 477 | 478 | if(alt && scancode == F1) 479 | { 480 | tty_switch(1); 481 | goto done; 482 | } 483 | */ 484 | uint8_t buf[2]; 485 | buf[1] = '\0'; 486 | 487 | if(ctl && kbd_us[scancode] == 'c') 488 | { 489 | if(tty->buf) tty->buf[i] = '\0'; 490 | if(tty->p) 491 | { 492 | signal_send(tty->p, SIGINT); 493 | tty->p->stat.rax = -1; 494 | } 495 | i = 0; 496 | tty->p = NULL; 497 | tty->buf = NULL; 498 | tty->len = 0; 499 | goto done; 500 | } 501 | 502 | if(scancode < 60) 503 | { 504 | if(shift) buf[0] = kbd_us_shift[scancode]; 505 | else 506 | buf[0] = kbd_us[scancode]; 507 | 508 | 509 | if(tty->p) 510 | (i < tty->len)?(tty->buf[i++] = buf[0]):(tty->buf[i] = '\0'); 511 | 512 | if(buf[0] == '\b') 513 | { 514 | if(tty->buf && i) 515 | { 516 | tty->buf[--i] = '\0'; 517 | if(i) 518 | { 519 | --i; 520 | ttydev_write(cur_tty, 0, 1, buf); 521 | } 522 | } 523 | } 524 | else ttydev_write(cur_tty, 0, 1, buf); 525 | 526 | if(kbd_us[scancode] == '\n') 527 | { 528 | if(tty->buf) tty->buf[i] = '\0'; 529 | if(tty->p) 530 | { 531 | tty->p->status = READY; 532 | tty->p->stat.rax = i; 533 | } 534 | i = 0; 535 | tty->p = NULL; 536 | tty->buf = NULL; 537 | tty->len = 0; 538 | } 539 | } 540 | 541 | done: 542 | if(cur_pdpt) switch_pdpt(cur_pdpt); 543 | return; 544 | 545 | } 546 | 547 | uint32_t ttydev_read(inode_t *inode, uint64_t offset_unused, uint64_t len, void *buf) 548 | { 549 | tty_device_t *tty = inode->p; 550 | if(!tty->p) tty->p = current_process; 551 | tty->p->status = WAITING; 552 | tty->buf = buf; 553 | tty->len = len; 554 | } 555 | 556 | /* 557 | void ttym_invoke(tty_device_t *tty, uint32_t req, ...) 558 | { 559 | va_list args; 560 | va_start(args, req); 561 | 562 | switch(req) 563 | { 564 | case TTYM_WRITE: //(buf, size, fg, bg) 565 | { 566 | uint8_t *buf = va_arg(args, uint8_t*); 567 | uint32_t size = va_arg(args, uint32_t); 568 | uint32_t fg = va_arg(args, uint32_t); 569 | uint32_t bg = va_arg(args, uint32_t); 570 | uint32_t i, cur = 0; 571 | for(i = 0; i < size; ++i) 572 | { 573 | tty->master->console->fs->ioctl( 574 | tty->master->console, 575 | 0, // request ( Draw Character ) 576 | (tty->pos + i) % tty->cols, //posx 577 | (tty->pos + i) / tty->cols, //posy 578 | buf[i], 579 | fg, 580 | bg 581 | ); 582 | } 583 | tty->pos += size; 584 | 585 | tty->master->console->fs->ioctl( 586 | tty->master->console, 587 | 1, // request ( Set Cursor ) 588 | tty->pos 589 | ); 590 | } 591 | break; 592 | case TTYM_SWITCH: 593 | 594 | debug("tty switch"); 595 | break; 596 | default: 597 | break; 598 | } 599 | } 600 | */ 601 | 602 | dev_t ttydev = 603 | (dev_t) 604 | { 605 | .probe = &ttydev_probe, 606 | .name = "ttydev", 607 | .read = &ttydev_read, 608 | .write = &ttydev_write, 609 | }; 610 | -------------------------------------------------------------------------------- /kernel/fs/Makefile: -------------------------------------------------------------------------------- 1 | 2 | include ../Makefile.cfg 3 | 4 | OBJ = vfs.o initramfs.o devfs.o ext2.o fsman.o 5 | OUT=../obj 6 | 7 | CFLAGS = -c -I ../include/ -mcmodel=large -nostdlib -ffreestanding 8 | 9 | all: $(OBJ) 10 | ${CP} $(OBJ) $(OUT) 11 | 12 | $(OUT)/%.o: %.c 13 | $(CC) $(CFLAGS) $< -o $@ 14 | 15 | clean: 16 | ${RM} -f $(OBJ) 17 | 18 | -------------------------------------------------------------------------------- /kernel/fs/devfs.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | inode_t dev_root = 6 | (inode_t){ 7 | .name = NULL, 8 | .size = 0, 9 | .type = FS_DIR, 10 | .parent = NULL, 11 | .list = NULL, 12 | .fs = &devfs, 13 | .dev = &ramdev, 14 | .p = NULL, 15 | .next = NULL, 16 | }; 17 | 18 | static uint64_t devfs_read(inode_t *inode, uint64_t offset, uint64_t size, void *buf) 19 | { 20 | return inode->dev->read(inode, offset, size, buf); 21 | } 22 | 23 | static uint64_t devfs_write(inode_t *inode, uint64_t offset, uint64_t size, void *buf) 24 | { 25 | return inode->dev->write(inode, offset, size, buf); 26 | } 27 | 28 | static uint32_t devfs_ioctl(inode_t *inode, uint64_t request, ...) 29 | { 30 | va_list args; 31 | va_start(args, request); 32 | return inode->dev->ioctl(inode, request, args); 33 | va_end(args); 34 | } 35 | 36 | static uint32_t devfs_mount(inode_t *dst, inode_t *src_unused) 37 | { 38 | vfs_mount(dst, "/", &dev_root); 39 | return 1; 40 | } 41 | 42 | fs_t devfs = 43 | (fs_t) 44 | { 45 | .name = "devfs", 46 | .read = &devfs_read, 47 | .write = &devfs_write, 48 | .ioctl = &devfs_ioctl, 49 | .mount = &devfs_mount, 50 | }; 51 | -------------------------------------------------------------------------------- /kernel/fs/ext2.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | typedef struct 10 | { 11 | ext2_superblock_t *sb; 12 | uint32_t inode; 13 | }ext2_private_t; 14 | 15 | 16 | ext2_inode_t *ext2_get_inode(inode_t *dev_inode, ext2_superblock_t *sb, uint32_t inode) 17 | { 18 | uint32_t bs = 1024 << sb->block_size; 19 | uint32_t block_group = (inode - 1) / sb->inodes_per_block_group; 20 | block_group_descriptor_t *bgd = kmalloc(sizeof(*bgd)); 21 | dev_inode->fs->read(dev_inode, 2 * bs + block_group, sizeof(*bgd), bgd); 22 | uint32_t index = (inode - 1) % sb->inodes_per_block_group; 23 | ext2_inode_t *i = kmalloc(sizeof(*i)); 24 | dev_inode->fs->read(dev_inode, bgd->inode_table * bs + index * sb->inode_size, sizeof(*i), i); 25 | return i; 26 | } 27 | 28 | uint32_t *get_block(inode_t *dev_inode, ext2_superblock_t *sb, uint32_t number, void *buf) 29 | { 30 | uint32_t bs = 1024 << sb->block_size; 31 | //uint32_t *ret = kmalloc(bs); 32 | dev_inode->fs->read(dev_inode, number * bs, bs, buf); 33 | return buf; 34 | } 35 | 36 | uint32_t *get_block_ptrs(inode_t *dev_inode, ext2_superblock_t *sb, ext2_inode_t *inode) 37 | { 38 | uint32_t bs = 1024 << sb->block_size; 39 | 40 | uint32_t isize = inode->size / bs + (inode->size % bs ? 1 : 0 ); 41 | uint32_t *blks = kmalloc(sizeof(uint32_t) * (isize + 1)); 42 | 43 | // The size is always saved as the first entry of the returned array 44 | blks[0] = isize; 45 | 46 | uint32_t k; 47 | for(k = 1; k <= 12 && k <= isize; ++k) 48 | blks[k] = inode->direct_pointer[k - 1]; 49 | 50 | if(isize <= 12) // Was that enough !? 51 | return blks; 52 | 53 | isize -= 12; 54 | 55 | 56 | uint32_t *tmp = get_block(dev_inode, sb, inode->singly_indirect_pointer, kmalloc(bs)); 57 | 58 | for(k = 0; k < (bs/4) && k <= isize; ++k) 59 | blks[13 + k] = tmp[k]; 60 | 61 | kfree(tmp); 62 | 63 | if(isize <= (bs/4)) // Are we done yet !? 64 | return blks; 65 | 66 | isize -= (bs/4); 67 | 68 | tmp = get_block(dev_inode, sb, inode->doubly_indirect_pointer, kmalloc(bs)); 69 | uint32_t *tmp2 = kmalloc(bs); 70 | 71 | uint32_t j; 72 | for(k = 0; k < (bs/4) && (k * (bs/4)) <= isize; ++k) 73 | { 74 | tmp2 = get_block(dev_inode, sb, tmp[k], tmp2); 75 | for(j = 0; j < (bs/4) && (k * (bs/4) + j) <= isize; ++j) 76 | { 77 | blks[13 + bs/4 + k * bs/4 + j] = tmp2[j]; 78 | } 79 | } 80 | 81 | if(isize <= (bs/4)*(bs/4)) 82 | return blks; 83 | 84 | kfree(tmp); 85 | 86 | // TODO : Support triply indirect pointers 87 | debug("File size too big\n"); 88 | for(;;); 89 | } 90 | 91 | inode_t *ext2_load(inode_t *dev_inode) 92 | { 93 | ext2_superblock_t *sb = kmalloc(sizeof(*sb)); 94 | vfs_read(dev_inode, 1024, sizeof(*sb), sb); 95 | 96 | if(sb->ext2_signature != 0xEF53) return NULL; 97 | //uint32_t *b = get_block(dev, sb, 2); 98 | 99 | uint32_t bs = 1024 << sb->block_size; // Block size 100 | uint32_t is = sb->inode_size; // Inode size 101 | 102 | block_group_descriptor_t *bgd = kmalloc(sizeof(*bgd)); 103 | vfs_read(dev_inode, (sb->block_size ? 1 : 2) * bs, sizeof(*bgd), (void*)bgd); 104 | 105 | ext2_inode_t *root_inode = kmalloc(is); 106 | vfs_read(dev_inode, bs * bgd->inode_table + is, is, root_inode); 107 | 108 | uint32_t *ptrs = get_block_ptrs(dev_inode, sb, root_inode); 109 | uint32_t count = *ptrs++; 110 | 111 | uint32_t k; 112 | 113 | ext2_dentry_t *_d = kmalloc(bs), *d; 114 | 115 | inode_t *ext2_vfs = kmalloc(sizeof(inode_t)); 116 | ext2_vfs->name = strdup("hd"); 117 | ext2_vfs->type = FS_DIR; 118 | ext2_vfs->list = kmalloc(sizeof(dentry_t)); 119 | ext2_vfs->list->count = 0; 120 | ext2_vfs->list->head = NULL; 121 | inode_t *_tmp = NULL; 122 | 123 | for(k = 0; k < count; ++k) 124 | { 125 | d = (ext2_dentry_t*)(get_block(dev_inode, sb, *(ptrs + k), _d)); 126 | if(d) 127 | { 128 | uint32_t size = 0; 129 | while(size <= bs) 130 | { 131 | if((!d->size) || (size + d->size > bs)) break; 132 | //if(d->name_length) 133 | { 134 | //uint8_t *s = strndup(d->name, d->name_length); 135 | //debug("%s\n", s); 136 | //kfree(s); 137 | } 138 | 139 | if(!_tmp) 140 | ext2_vfs->list->head = _tmp = kmalloc(sizeof(inode_t)); 141 | else 142 | _tmp = _tmp->next = kmalloc(sizeof(inode_t)); 143 | 144 | _tmp->next = NULL; 145 | _tmp->name = strndup(d->name, d->name_length); 146 | debug("%s\n", _tmp->name); 147 | ext2_inode_t *_inode = ext2_get_inode(dev_inode, sb, d->inode); 148 | _tmp->size = _inode->size; 149 | kfree(_inode); 150 | _tmp->type = FS_FILE; 151 | _tmp->dev = dev_inode->dev; 152 | _tmp->fs = &ext2fs; 153 | _tmp->p = kmalloc(sizeof(ext2_private_t)); 154 | *(ext2_private_t*)_tmp->p = (ext2_private_t) 155 | { 156 | .sb = sb, 157 | .inode = d->inode, 158 | }; 159 | ext2_vfs->list->count++; 160 | 161 | size += d->size; 162 | d = (ext2_dentry_t*)((uint64_t)d + d->size); 163 | } 164 | //kfree(d); 165 | } 166 | } 167 | 168 | kfree(_d); 169 | 170 | return ext2_vfs; 171 | } 172 | 173 | uint64_t ext2_read(inode_t *inode, uint64_t offset, uint64_t size, void *buf) 174 | { 175 | uint32_t _size = size; 176 | 177 | debug("Reading file %s\n", inode->name); 178 | ext2_private_t *p = inode->p; 179 | 180 | uint32_t bs = 1024 << p->sb->block_size; 181 | ext2_inode_t *i = ext2_get_inode(inode, p->sb, p->inode); 182 | 183 | uint32_t *ptrs = get_block_ptrs(inode, p->sb, i); 184 | uint32_t count = *ptrs++; 185 | 186 | uint32_t skip_blocks = offset/bs; // Blocks to be skipped 187 | uint32_t skip_bytes = offset%bs; // Bytes to be skipped 188 | 189 | if(count < skip_blocks) return 0; 190 | 191 | count -= skip_blocks; 192 | ptrs += skip_blocks; 193 | 194 | // Now let's read the first part ( size <= bs ) 195 | uint32_t first_part_size = (count > 1)?MIN(bs - skip_bytes, size):MIN(size, inode->size); 196 | inode->dev->read(inode, (*ptrs++) * bs + skip_bytes, first_part_size, buf); 197 | buf += first_part_size; 198 | size -= first_part_size; 199 | --count; 200 | 201 | // Now let's read the second part ( size is a multible of bs ) 202 | while(count > 1 && size > bs) 203 | { 204 | inode->dev->read(inode, *ptrs++ * bs, bs, buf); 205 | buf += bs; 206 | size -= bs; 207 | --count; 208 | } 209 | 210 | // Now let's read the last part ( size <= bs) 211 | if(count) 212 | { 213 | uint32_t last_part_size = MIN(size, inode->size - ( _size - size )); 214 | inode->dev->read(inode, (*ptrs++) * bs, last_part_size, buf); 215 | buf += last_part_size; 216 | size -= last_part_size; 217 | --count; 218 | } 219 | 220 | return _size - size; 221 | 222 | } 223 | 224 | static uint32_t ext2_mount(inode_t *dst, inode_t *src) 225 | { 226 | inode_t *i = ext2_load(src); 227 | 228 | if(!i) return -1; 229 | vfs_mount(dst, "/", i); 230 | 231 | return 1; 232 | } 233 | 234 | /* 235 | file_t *ext2_open(inode_t *inode) 236 | { 237 | file_t *ret = kmalloc(sizeof(file_t)); 238 | ret->pos = 0; 239 | ret->size = inode->size; 240 | ret->buf = kmalloc(30); 241 | debug("size %d\n", inode->size); 242 | inode->fs->fs->read(inode, 0ret->buf, 20); 243 | return ret; 244 | } 245 | */ 246 | fs_t ext2fs = 247 | (fs_t) 248 | { 249 | .name = "ext2", 250 | .load = ext2_load, 251 | //.open = NULL, 252 | .read = ext2_read, 253 | .write = NULL, 254 | .mount = &ext2_mount, 255 | }; 256 | -------------------------------------------------------------------------------- /kernel/fs/fsman.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | fs_t * filesystems[] = 10 | { 11 | &initramfs, 12 | &devfs, 13 | &ext2fs, 14 | NULL, 15 | }; 16 | 17 | static void fsman_init() 18 | { 19 | debug("Loading filesystems "); 20 | fs_t **fs = filesystems; 21 | while(*fs) 22 | { 23 | debug("."); 24 | ++fs; 25 | } 26 | 27 | debug(" [done]\n"); 28 | } 29 | 30 | static fs_t * fsman_getfs(uint8_t *name) 31 | { 32 | if(!name) return NULL; 33 | fs_t **fs = filesystems; 34 | while(*fs) 35 | { 36 | if((*fs)->name && !strcmp(name, (*fs)->name)) 37 | return *fs; 38 | ++fs; 39 | } 40 | return NULL; 41 | } 42 | 43 | fsman_t fsman = (fsman_t) 44 | { 45 | .init = &fsman_init, 46 | .getfs = &fsman_getfs, 47 | }; 48 | -------------------------------------------------------------------------------- /kernel/fs/initramfs.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | static inode_t *cpiofs_load(inode_t *inode) 8 | { 9 | inode_t *rootfs = kmalloc(sizeof(inode_t)); 10 | 11 | rootfs->name = NULL; 12 | rootfs->type = FS_DIR; 13 | rootfs->parent = NULL; 14 | rootfs->fs = &initramfs; 15 | rootfs->list = kmalloc(sizeof(dentry_t)); 16 | dentry_t *list = rootfs->list; 17 | 18 | list->count = 0; 19 | 20 | dentry_t *tmp; 21 | 22 | cpio_hdr_t *cpio = ((ramdev_private_t*)inode->p)->ptr; 23 | 24 | debug("Loading ramdisk "); 25 | while(*(uint8_t*)cpio) 26 | { 27 | uint32_t size = cpio->filesize[0] * 0x10000 + cpio->filesize[1]; 28 | uint8_t *name = (uint8_t*)cpio + sizeof(*cpio); 29 | if(!strcmp(name, "TRAILER!!!")) break; 30 | if(!strcmp(name, ".")) goto next; 31 | uint8_t *filename; uint32_t i; 32 | for( i = cpio->namesize - 1; i && (name[i] != '/'); --i); 33 | filename = name + (i?++i:i); 34 | uint8_t *path = strdup(name); 35 | path[i] = '\0'; 36 | inode_type type = ((cpio->mode & 0170000 ) == 0040000)?FS_DIR:FS_FILE; 37 | 38 | void *data = name + cpio->namesize + cpio->namesize%2; 39 | inode_t *new_node = kmalloc(sizeof(inode_t)); 40 | *new_node = 41 | (inode_t) 42 | { 43 | .name = strdup(filename), 44 | .size = size, 45 | .type = type, 46 | .fs = &initramfs, 47 | .p = data, 48 | }; 49 | 50 | vfs_create(rootfs, *path ? path : (uint8_t*)"/", new_node); 51 | kfree(path); 52 | 53 | next: 54 | cpio = (typeof(cpio)) 55 | (name + cpio->namesize + (cpio->namesize%2) + size + (size%2)); 56 | debug("."); 57 | } 58 | debug(" [done]\n"); 59 | 60 | return rootfs; 61 | } 62 | 63 | static uint64_t cpiofs_read(inode_t *inode, uint64_t offset, uint64_t len, void *buf_p) 64 | { 65 | uint8_t *buf = (uint8_t*)buf_p; 66 | if(offset > inode->size) return 0; 67 | uint32_t size = MIN(len, inode->size - offset), _size = size; 68 | uint8_t *_buf = (uint8_t*)inode->p + offset; 69 | while(size--) 70 | *buf++ = *_buf++; 71 | 72 | return _size; 73 | } 74 | 75 | fs_t initramfs = 76 | (fs_t) 77 | { 78 | .name = "initramfs", 79 | .load = cpiofs_load, 80 | .read = cpiofs_read, 81 | .write = NULL, 82 | }; 83 | -------------------------------------------------------------------------------- /kernel/fs/vfs.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | inode_t *vfs_root; 8 | 9 | void vfs_mount_root(inode_t *node) 10 | { 11 | vfs_root = kmalloc(sizeof(inode_t)); 12 | vfs_mount(vfs_root, "/", node); 13 | } 14 | 15 | inode_t *vfs_trace_path(inode_t *inode, uint8_t *_path) 16 | { 17 | if(!_path || (_path && !*_path)) return inode; 18 | uint8_t *path = strdup(_path); 19 | uint32_t len = strlen(path); 20 | uint8_t *end_path = path + len; 21 | uint32_t i; 22 | for( i = 0; i < len; ++i) 23 | if(path[i] == '/') 24 | path[i] = '\0'; 25 | 26 | if((!*path) && len == 1) return inode; 27 | if(!*path) ++path; 28 | 29 | inode_t *tmp = inode; 30 | 31 | while(tmp) 32 | { 33 | if(tmp->type == FS_MOUNTPOINT) 34 | tmp = ((vfs_mountpoint_t*)tmp->p)->inode; 35 | 36 | if(!tmp->list) return NULL; 37 | if(!tmp->list->count) return NULL; 38 | uint32_t k = 0; 39 | inode_t *_tmp = tmp->list->head; 40 | if(!_tmp) return NULL; 41 | while(_tmp && k < tmp->list->count) 42 | { 43 | if(!strcmp(path, _tmp->name)) break; 44 | _tmp = _tmp->next; 45 | ++k; 46 | } 47 | if( !_tmp || !_tmp->name || strcmp(path, _tmp->name) ) return NULL; 48 | tmp = _tmp; 49 | while(path < end_path && *path++); 50 | if(path >= end_path) return tmp; 51 | } 52 | } 53 | 54 | inode_t *vfs_create(inode_t *root, uint8_t *path, inode_t *new_node) 55 | { 56 | inode_t *dir = vfs_trace_path(root, path); 57 | 58 | if(!dir) return NULL; 59 | if(!dir->list) 60 | { 61 | dir->list = kmalloc(sizeof(dentry_t)); 62 | dir->list->count = 0; 63 | } 64 | uint32_t k; 65 | 66 | if(!dir->list->head) dir->list->head = kmalloc(sizeof(inode_t)); 67 | 68 | ++dir->list->count; 69 | new_node->next = dir->list->head; 70 | new_node->parent = dir; 71 | dir->list->head = new_node; 72 | return new_node; 73 | } 74 | 75 | inode_t *vfs_mount(inode_t *root, uint8_t *path, inode_t *new_node) 76 | { 77 | inode_t *dir = vfs_trace_path(root, path); 78 | if(!dir) return NULL; 79 | 80 | inode_t *tmp = kmalloc(sizeof(inode_t)); 81 | memcpy(tmp, dir, sizeof(inode_t)); 82 | 83 | dir->type = FS_MOUNTPOINT; 84 | 85 | vfs_mountpoint_t *mount = kmalloc(sizeof(vfs_mountpoint_t)); 86 | mount->inode = new_node; 87 | mount->old_inode = tmp; 88 | 89 | dir->p = mount; 90 | //dir->fs = &vfs; 91 | 92 | return dir; 93 | } 94 | 95 | void vfs_tree(inode_t *node) 96 | { 97 | static uint32_t level = 0; 98 | if(!node) return; 99 | if(node->name) debug("%s", node->name); 100 | if(node->type == FS_DIR || node->type == FS_MOUNTPOINT) 101 | { 102 | debug("/"); 103 | if(node->type == FS_MOUNTPOINT) 104 | { 105 | vfs_mountpoint_t *m = node->p; 106 | vfs_tree(m->inode); 107 | return; 108 | } 109 | if(node->list) 110 | { 111 | debug("\n"); 112 | ++level; 113 | uint32_t i, j; 114 | for(j = 0; j < node->list->count; ++j) 115 | { 116 | if(level > 1) 117 | for(i = 1; i < 2 * level - 2; ++i) debug(" "); 118 | debug("→ "); 119 | 120 | inode_t *tmp = node->list->head; 121 | uint32_t k = 0; 122 | while(k++ < j) tmp = tmp->next; 123 | vfs_tree(tmp); 124 | debug("\n"); 125 | } 126 | --level; 127 | return; 128 | } 129 | } 130 | } 131 | 132 | uint64_t vfs_read(inode_t *inode, uint64_t offset, uint64_t len, void *buf) 133 | { 134 | return inode->fs->read(inode, offset, len, buf); 135 | } 136 | 137 | uint64_t vfs_write(inode_t *inode, uint64_t offset, uint64_t len, void *buf) 138 | { 139 | return inode->fs->write(inode, offset, len, buf); 140 | } 141 | -------------------------------------------------------------------------------- /kernel/include/ata.h: -------------------------------------------------------------------------------- 1 | #ifndef _ATA_H 2 | #define _ATA_H 3 | 4 | #include 5 | #include 6 | 7 | #define ATA_LBA_MODE 0xE0 8 | #define ATA_SECT 0x1F2 // number of sectors 9 | #define ATA_LBA0 0x1F3 // bits 0 to 7 10 | #define ATA_LBA1 0x1F4 // bits 8 to 15 11 | #define ATA_LBA2 0x1F5 // bits 16 to 23 12 | #define ATA_LBA3 0x1F6 // bits 24 to 27 & drive & mode 13 | #define ATA_CMD 0x1F7 // command port / status register 14 | #define ATA_DATA 0x1F0 // data port 15 | #define ATA_READ 0x20 // LBA Read with retry command 16 | #define ATA_WRITE 0x30 // LBA write with retry command 17 | #define ATA_DRV0 0x00 // first drive 18 | #define ATA_DRV1 0x10 // second drive 19 | 20 | typedef struct 21 | { 22 | uint64_t start_lba; 23 | uint64_t end_lba; 24 | } atadev_private_t; 25 | 26 | extern dev_t atadev; 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /kernel/include/config.h: -------------------------------------------------------------------------------- 1 | #ifndef _CONFIG_H 2 | #define _CONFIG_H 3 | 4 | #define _DEBUG_ 1 5 | #define _DBG_CON_ 0 // Debug to Console 6 | #define _GFX_ 0 7 | #define _LAZYALLOC_ 1 8 | 9 | #define _BMPMEM_ 1 10 | #define _STKMEM_ 2 11 | #define _PMEM_ _BMPMEM_ 12 | #define _PMEM_ACLR 1 // Physical memory auto-clear page 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /kernel/include/console.h: -------------------------------------------------------------------------------- 1 | #ifndef _CONSOLE_H 2 | #define _CONSOLE_H 3 | 4 | #include 5 | #include 6 | 7 | typedef struct virtcon_struct virtcon_device_t; 8 | 9 | struct virtcon_struct 10 | { 11 | uint8_t *buf; 12 | uint32_t pos, h, w; 13 | 14 | void (*putc)(virtcon_device_t *virtcon, uint8_t chr, uint32_t x, 15 | uint32_t y, uint32_t fg, uint32_t bg); 16 | void (*puts)(virtcon_device_t *virtcon, uint8_t *str, uint32_t size, 17 | uint32_t x, uint32_t y, uint32_t fg, uint32_t bg); 18 | void (*setcur)(virtcon_device_t *virtcon, uint32_t c, uint32_t r); 19 | void (*scroll)(virtcon_device_t *virtcon, uint32_t n); 20 | void (*draw)(virtcon_device_t *virtcon); 21 | tty_device_t *tty; 22 | }; 23 | 24 | virtcon_device_t *get_virtcon(tty_device_t *tty, uint32_t w, uint32_t h); 25 | 26 | #endif 27 | -------------------------------------------------------------------------------- /kernel/include/debug.h: -------------------------------------------------------------------------------- 1 | #ifndef _DEBUG_H 2 | #define _DEBUG_H 3 | 4 | #if _DEBUG_ > 0 5 | void debug(uint8_t *, ...); 6 | #else 7 | #define debug(...) 8 | #endif 9 | 10 | #endif 11 | -------------------------------------------------------------------------------- /kernel/include/devfs.h: -------------------------------------------------------------------------------- 1 | #ifndef _DEVFS_H 2 | #define _DEVFS_H 3 | 4 | extern inode_t dev_root; 5 | extern fs_t devfs; 6 | 7 | #endif 8 | -------------------------------------------------------------------------------- /kernel/include/device.h: -------------------------------------------------------------------------------- 1 | #ifndef _DEVICE_H 2 | #define _DEVICE_H 3 | 4 | #include 5 | #include 6 | 7 | typedef enum 8 | { 9 | DEV_CHR = 1, 10 | DEV_BLK = 2, 11 | } dev_type; 12 | 13 | typedef struct dev_struct dev_t; 14 | 15 | #include 16 | 17 | struct dev_struct 18 | { 19 | uint8_t *name; 20 | dev_type type; 21 | uint32_t (*probe)(inode_t *inode); 22 | uint32_t (*read) (inode_t *inode, uint64_t offset, uint64_t size, void *buf); 23 | uint32_t (*write)(inode_t *inode, uint64_t offset, uint64_t size, void *buf); 24 | uint32_t (*ioctl)(inode_t *inode, uint64_t request, va_list args); 25 | // void *p; // To be used by device handler 26 | } __attribute__((packed)); 27 | 28 | extern dev_t ramdev; 29 | extern dev_t condev; 30 | 31 | typedef struct ramdev_private_struct 32 | { 33 | void *ptr; 34 | uint64_t size; 35 | }ramdev_private_t; 36 | 37 | typedef struct 38 | { 39 | void (*init)(void); 40 | } devman_t; 41 | 42 | extern devman_t devman; 43 | 44 | #endif 45 | -------------------------------------------------------------------------------- /kernel/include/elf.h: -------------------------------------------------------------------------------- 1 | #ifndef _ELF_H 2 | #define _ELF_H 3 | 4 | typedef struct 5 | { 6 | uint8_t magic[4]; 7 | uint8_t class; 8 | uint8_t endian; 9 | uint8_t elf_version; 10 | uint8_t abi; 11 | uint8_t abi_version; 12 | uint8_t pad[7]; 13 | uint16_t type; 14 | uint16_t machine; 15 | uint32_t version; 16 | uint64_t entry; 17 | uint64_t phoff; 18 | uint64_t shoff; 19 | uint32_t flags; 20 | uint16_t ehsize; 21 | uint16_t phentsize; 22 | uint16_t phnum; 23 | uint16_t shentsize; 24 | uint16_t shnum; 25 | uint16_t shstrndx; 26 | } elf_hdr_t; 27 | 28 | typedef struct 29 | { 30 | uint32_t name; 31 | uint32_t type; 32 | uint64_t flags; 33 | uint64_t addr; 34 | uint64_t off; 35 | uint64_t size; 36 | uint32_t link; 37 | uint32_t info; 38 | uint64_t addralign; 39 | uint64_t entsize; 40 | } elf_section_hdr_t; 41 | 42 | #endif 43 | -------------------------------------------------------------------------------- /kernel/include/ext2.h: -------------------------------------------------------------------------------- 1 | #ifndef _EXT2_H 2 | #define _EXT2_H 3 | 4 | #include 5 | #include 6 | 7 | #define __packed __attribute__((packed)) 8 | 9 | typedef struct 10 | { 11 | uint8_t preallocate_for_directories : 1; 12 | uint8_t afs_server_inodes : 1; 13 | uint8_t has_journaling : 1; // for EXT 3 14 | uint8_t inodes_have_extended_attributes : 1; 15 | uint8_t can_be_resized : 1; 16 | uint8_t directories_use_hash_index : 1; 17 | } __packed optional_features_flags_t; 18 | 19 | typedef struct 20 | { 21 | uint8_t compressed : 1; 22 | uint8_t directories_has_types : 1; 23 | uint8_t needs_to_replay_journal : 1; 24 | uint8_t uses_journal_device : 1; 25 | } __packed required_features_flags_t; 26 | 27 | typedef struct 28 | { 29 | uint8_t sparse_sb_and_gdt : 1; 30 | uint8_t uses_64bit_file_size : 1; 31 | uint8_t directories_contents_are_binary_tree : 1; 32 | } __packed read_only_features_flags_t; 33 | 34 | typedef struct 35 | { 36 | uint32_t inodes_count; 37 | uint32_t blocks_count; 38 | uint32_t su_blocks_count; 39 | uint32_t unallocated_blocks_count; 40 | uint32_t unallocated_inodes_count; 41 | uint32_t su_block_number; 42 | uint32_t block_size; 43 | uint32_t fragment_size; 44 | uint32_t blocks_per_block_group; 45 | uint32_t fragments_per_block_group; 46 | uint32_t inodes_per_block_group; 47 | uint32_t last_mount_time; 48 | uint32_t last_written_time; 49 | uint16_t times_mounted; // after last fsck 50 | uint16_t allowed_times_mounted; 51 | uint16_t ext2_signature; 52 | uint16_t filesystem_state; 53 | uint16_t on_error; 54 | uint16_t minor_version; 55 | uint32_t last_fsck; 56 | uint32_t time_between_fsck; // Time allowed between fsck(s) 57 | uint32_t os_id; 58 | uint32_t major_version; 59 | uint16_t uid; 60 | uint16_t gid; 61 | 62 | // For extended superblock fields ... which is always assumed 63 | uint32_t first_non_reserved_inode; 64 | uint16_t inode_size; 65 | uint16_t sb_block_group; 66 | optional_features_flags_t optional_features; 67 | required_features_flags_t required_features; 68 | read_only_features_flags_t read_only_features; 69 | uint8_t fsid[16]; 70 | uint8_t name[16]; 71 | uint8_t path_last_mounted_to[64]; 72 | uint32_t compression_algorithms; 73 | uint8_t blocks_to_preallocate_for_files; 74 | uint8_t blocks_to_preallocate_for_directories; 75 | uint16_t __unused__; 76 | uint8_t jid[16]; // Journal ID 77 | uint32_t jinode; // Journal inode 78 | uint32_t jdevice; // Journal device 79 | uint32_t head_of_orphan_inode_list; // What the hell is this !? 80 | } __packed ext2_superblock_t; 81 | 82 | typedef struct 83 | { 84 | uint32_t block_usage_bitmap; 85 | uint32_t inode_usage_bitmap; 86 | uint32_t inode_table; 87 | uint16_t unallocated_blocks_count; 88 | uint16_t unallocated_inodes_count; 89 | uint16_t directories_count; 90 | uint8_t __unused__[14]; 91 | } __packed block_group_descriptor_t; 92 | 93 | #define ext2_inode_type_FIFO 0x1 // FIFO pipe 94 | #define ext2_inode_type_CHR 0x2 // Character device 95 | #define ext2_inode_type_DIR 0x4 // Directory 96 | #define ext2_inode_type_BLK 0x6 // Block device 97 | #define ext2_inode_type_RGL 0x8 // Regular file 98 | #define ext2_inode_type_SLINK 0xA // Symbolic link 99 | #define ext2_inode_type_SCKT 0xC // Unix socket 100 | 101 | typedef struct 102 | { 103 | uint8_t other_exec : 1; 104 | uint8_t other_write : 1; 105 | uint8_t other_read : 1; 106 | uint8_t group_exec : 1; 107 | uint8_t group_write : 1; 108 | uint8_t group_read : 1; 109 | uint8_t user_exec : 1; 110 | uint8_t user_write : 1; 111 | uint8_t user_read : 1; 112 | } __packed ext2_inode_permissions_t; 113 | 114 | typedef struct 115 | { 116 | uint16_t permissions : 12; 117 | uint16_t type : 4; 118 | uint16_t uid; 119 | uint32_t size; 120 | uint32_t last_access_time; 121 | uint32_t creation_time; 122 | uint32_t last_modified_time; 123 | uint32_t deletion_time; // Wha !? 124 | uint16_t gid; 125 | uint16_t hard_links_count; 126 | uint32_t sectors_count; 127 | uint32_t flags; 128 | uint32_t os_specific1; 129 | uint32_t direct_pointer[12]; 130 | uint32_t singly_indirect_pointer; 131 | uint32_t doubly_indirect_pointer; 132 | uint32_t triply_indirect_pointer; 133 | uint32_t generation_number; 134 | uint32_t extended_attribute_block; 135 | uint32_t size_high; 136 | uint32_t fragment; 137 | uint8_t os_specific2[12]; 138 | } __packed ext2_inode_t; 139 | 140 | typedef struct 141 | { 142 | uint32_t inode; 143 | uint16_t size; 144 | uint8_t name_length; 145 | uint8_t type; 146 | uint8_t name[0]; // Name will be here 147 | } __packed ext2_dentry_t; 148 | 149 | #define ext2_dir_type_BAD 0 150 | #define ext2_dir_type_RGL 1 151 | #define ext2_dir_type_DIR 2 152 | #define ext2_dir_type_CHR 3 153 | #define ext2_dir_type_BLK 4 154 | #define ext2_dir_type_FIFO 5 155 | #define ext2_dir_type_SCKT 6 156 | #define ext2_dir_type_SLINK 7 157 | 158 | extern fs_t ext2fs; 159 | 160 | #endif 161 | -------------------------------------------------------------------------------- /kernel/include/fpu.h: -------------------------------------------------------------------------------- 1 | #ifndef _FPU_H 2 | #define _FPU_H 3 | 4 | #include 5 | 6 | extern uint8_t fpu_state; 7 | 8 | void save_fpu(); 9 | void restore_fpu(); 10 | void trap_fpu(); 11 | void enable_fpu(); 12 | void disable_fpu(); 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /kernel/include/gdt.h: -------------------------------------------------------------------------------- 1 | #ifndef _GDT_H 2 | #define _GDT_H 3 | 4 | #include 5 | 6 | typedef struct 7 | { 8 | uint32_t limit_low : 16; 9 | uint32_t base_low : 24; 10 | uint8_t type : 4; 11 | uint8_t system : 1; 12 | uint8_t dpl : 2; 13 | uint8_t present : 1; 14 | uint16_t limit_high : 4; 15 | uint8_t avilable : 1; 16 | uint8_t longmode : 1; 17 | uint8_t size : 1; 18 | uint8_t gran : 1; 19 | uint32_t base_high : 8; 20 | } __attribute__((packed)) gdt_entry_t; 21 | 22 | typedef struct 23 | { 24 | uint16_t limit; 25 | uint64_t base; 26 | } gdt_ptr_t; 27 | 28 | 29 | typedef struct 30 | { 31 | uint32_t limit_low : 16; 32 | uint32_t base_low : 24; 33 | uint8_t type : 4; 34 | uint8_t _0_1 : 1; 35 | uint8_t dpl : 2; 36 | uint8_t present : 1; 37 | uint8_t limit_high : 4; 38 | uint8_t avilable : 1; 39 | uint8_t _0_2 : 2; 40 | uint8_t gran : 1; 41 | uint64_t base_high : 40; 42 | uint8_t _reserved1 : 8; 43 | uint8_t _0_3 : 5; 44 | uint32_t _reserved2 : 19; 45 | } __attribute__((packed)) tss64_seg_t; 46 | 47 | typedef struct 48 | { 49 | uint32_t _reserved; 50 | uint32_t rsp0_low; 51 | uint32_t rsp0_high; 52 | uint32_t _unused_in_our_kernel[23]; 53 | } tss64_t; 54 | 55 | #endif 56 | -------------------------------------------------------------------------------- /kernel/include/idt.h: -------------------------------------------------------------------------------- 1 | #ifndef _IDT_H 2 | #define _IDT_H 3 | 4 | #include 5 | 6 | typedef struct 7 | { 8 | uint16_t offset_low; 9 | uint16_t selector; 10 | uint8_t set_to_0; 11 | uint8_t flags; 12 | uint16_t offset_mid; 13 | uint32_t offset_high; 14 | uint32_t __reserved__space__not__used; 15 | } __attribute__((packed)) idt_entry_t; 16 | 17 | typedef struct 18 | { 19 | uint16_t limit; 20 | uint64_t base; 21 | } __attribute__((packed)) idt_ptr_t; 22 | 23 | idt_entry_t idt[256]; 24 | idt_ptr_t idt_ptr; 25 | 26 | void idt_set_gate(uint32_t, uint64_t, uint16_t, uint8_t); 27 | void idt_install(); 28 | 29 | #endif 30 | -------------------------------------------------------------------------------- /kernel/include/initramfs.h: -------------------------------------------------------------------------------- 1 | #ifndef _INITRAMFS_H 2 | #define _INITRAMFS_H 3 | 4 | #include 5 | #include 6 | 7 | extern fs_t initramfs; 8 | 9 | typedef struct 10 | { 11 | uint16_t magic; 12 | uint16_t dev; 13 | uint16_t ino; 14 | uint16_t mode; 15 | uint16_t uid; 16 | uint16_t gid; 17 | uint16_t nlink; 18 | uint16_t rdev; 19 | uint16_t mtimes[2]; 20 | uint16_t namesize; 21 | uint16_t filesize[2]; 22 | } cpio_hdr_t; 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /kernel/include/io.h: -------------------------------------------------------------------------------- 1 | inline uint8_t inb(uint32_t port); 2 | inline void outb(uint32_t port, uint8_t val); 3 | -------------------------------------------------------------------------------- /kernel/include/isr.h: -------------------------------------------------------------------------------- 1 | #ifndef _ISR_H 2 | #define _ISR_H 3 | 4 | #include 5 | 6 | typedef struct 7 | { 8 | uint64_t 9 | r15, r14, r13, r12, r11, r10, r9, r8, 10 | rdi, rsi, rbp, rbx, rcx, rdx, rax, 11 | rip, cs, rflags, rsp, ss; 12 | } __attribute__((packed)) regs_t; 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /kernel/include/kbd.h: -------------------------------------------------------------------------------- 1 | #ifndef _KBD_H 2 | #define _KBD_H 3 | 4 | #include 5 | #include 6 | 7 | void kbd_load(void*); 8 | void kbd_handler(regs_t*); 9 | 10 | #endif 11 | -------------------------------------------------------------------------------- /kernel/include/kmem.h: -------------------------------------------------------------------------------- 1 | #ifndef _KMEM_H 2 | #define _KMEM_H 3 | 4 | #include 5 | #include 6 | 7 | uint64_t *UPD; // User page directory 8 | uint64_t *PML4; 9 | uint64_t *KPD; // Kernel page directory 10 | uint8_t *kernel_heap_ptr; 11 | 12 | extern uint64_t total_mem; 13 | extern uint64_t total_usable_mem; 14 | 15 | extern multiboot_info_t *mboot_info; 16 | extern uint32_t kernel_size; 17 | extern uint32_t heap_addr; 18 | extern uint32_t heap_size; 19 | extern uint32_t kernel_heap_size; 20 | extern uint32_t VMA; 21 | //extern uint32_t kend; 22 | uint64_t kernel_end; 23 | //uint8_t *kernel_heap_ptr; 24 | 25 | typedef struct { 26 | uint64_t (*set) (uint64_t); 27 | uint64_t (*set_pages) (uint64_t, uint32_t); 28 | uint64_t (*clear) (uint64_t); 29 | uint64_t (*clear_pages) (uint64_t, uint32_t); 30 | uint32_t (*check) (uint64_t); 31 | void (*set_usable) (uint64_t, uint64_t); 32 | void (*set_unusable) (uint64_t, uint64_t); 33 | uint64_t (*get_frame) (); 34 | uint64_t (*get_frames) (uint32_t); 35 | void (*setup) (uint64_t); 36 | void (*dump) (); 37 | } mman_t; 38 | 39 | mman_t mman; 40 | void *memset(void*, uint8_t, uint32_t); 41 | 42 | void map_mem(multiboot_info_t*); 43 | void vmem_init(); 44 | void *kmalloc(uint32_t); 45 | void free(void*); 46 | 47 | void inline TLB_flush(); 48 | 49 | #endif 50 | -------------------------------------------------------------------------------- /kernel/include/multiboot.h: -------------------------------------------------------------------------------- 1 | /* multiboot.h - Multiboot header file. */ 2 | /* Copyright (C) 1999,2003,2007,2008,2009 Free Software Foundation, Inc. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to 6 | * deal in the Software without restriction, including without limitation the 7 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 8 | * sell copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ANY 17 | * DEVELOPER OR DISTRIBUTOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 18 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 19 | * IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 | */ 21 | #include 22 | 23 | #ifndef MULTIBOOT_HEADER 24 | #define MULTIBOOT_HEADER 1 25 | 26 | /* How many bytes from the start of the file we search for the header. */ 27 | #define MULTIBOOT_SEARCH 8192 28 | 29 | /* The magic field should contain this. */ 30 | #define MULTIBOOT_HEADER_MAGIC 0x1BADB002 31 | 32 | /* This should be in %eax. */ 33 | #define MULTIBOOT_BOOTLOADER_MAGIC 0x2BADB002 34 | 35 | /* The bits in the required part of flags field we don't support. */ 36 | #define MULTIBOOT_UNSUPPORTED 0x0000fffc 37 | 38 | /* Alignment of multiboot modules. */ 39 | #define MULTIBOOT_MOD_ALIGN 0x00001000 40 | 41 | /* Alignment of the multiboot info structure. */ 42 | #define MULTIBOOT_INFO_ALIGN 0x00000004 43 | 44 | /* Flags set in the 'flags' member of the multiboot header. */ 45 | 46 | /* Align all boot modules on i386 page (4KB) boundaries. */ 47 | #define MULTIBOOT_PAGE_ALIGN 0x00000001 48 | 49 | /* Must pass memory information to OS. */ 50 | #define MULTIBOOT_MEMORY_INFO 0x00000002 51 | 52 | /* Must pass video information to OS. */ 53 | #define MULTIBOOT_VIDEO_MODE 0x00000004 54 | 55 | /* This flag indicates the use of the address fields in the header. */ 56 | #define MULTIBOOT_AOUT_KLUDGE 0x00010000 57 | 58 | /* Flags to be set in the 'flags' member of the multiboot info structure. */ 59 | 60 | /* is there basic lower/upper memory information? */ 61 | #define MULTIBOOT_INFO_MEMORY 0x00000001 62 | /* is there a boot device set? */ 63 | #define MULTIBOOT_INFO_BOOTDEV 0x00000002 64 | /* is the command-line defined? */ 65 | #define MULTIBOOT_INFO_CMDLINE 0x00000004 66 | /* are there modules to do something with? */ 67 | #define MULTIBOOT_INFO_MODS 0x00000008 68 | 69 | /* These next two are mutually exclusive */ 70 | 71 | /* is there a symbol table loaded? */ 72 | #define MULTIBOOT_INFO_AOUT_SYMS 0x00000010 73 | /* is there an ELF section header table? */ 74 | #define MULTIBOOT_INFO_ELF_SHDR 0X00000020 75 | 76 | /* is there a full memory map? */ 77 | #define MULTIBOOT_INFO_MEM_MAP 0x00000040 78 | 79 | /* Is there drive info? */ 80 | #define MULTIBOOT_INFO_DRIVE_INFO 0x00000080 81 | 82 | /* Is there a config table? */ 83 | #define MULTIBOOT_INFO_CONFIG_TABLE 0x00000100 84 | 85 | /* Is there a boot loader name? */ 86 | #define MULTIBOOT_INFO_BOOT_LOADER_NAME 0x00000200 87 | 88 | /* Is there a APM table? */ 89 | #define MULTIBOOT_INFO_APM_TABLE 0x00000400 90 | 91 | /* Is there video information? */ 92 | #define MULTIBOOT_INFO_VIDEO_INFO 0x00000800 93 | 94 | #ifndef ASM_FILE 95 | /* 96 | typedef unsigned shortuint16_t; 97 | typedef unsigned int uint32_t; 98 | typedef unsigned long long uint64_t; 99 | */ 100 | struct multiboot_header 101 | { 102 | /* Must be MULTIBOOT_MAGIC - see above. */ 103 | uint32_t magic; 104 | 105 | /* Feature flags. */ 106 | uint32_t flags; 107 | 108 | /* The above fields plus this one must equal 0 mod 2^32. */ 109 | uint32_t checksum; 110 | 111 | /* These are only valid if MULTIBOOT_AOUT_KLUDGE is set. */ 112 | uint32_t header_addr; 113 | uint32_t load_addr; 114 | uint32_t load_end_addr; 115 | uint32_t bss_end_addr; 116 | uint32_t entry_addr; 117 | 118 | /* These are only valid if MULTIBOOT_VIDEO_MODE is set. */ 119 | uint32_t mode_type; 120 | uint32_t width; 121 | uint32_t height; 122 | uint32_t depth; 123 | }; 124 | 125 | /* The symbol table for a.out. */ 126 | struct multiboot_aout_symbol_table 127 | { 128 | uint32_t tabsize; 129 | uint32_t strsize; 130 | uint32_t addr; 131 | uint32_t reserved; 132 | }; 133 | typedef struct multiboot_aout_symbol_table multiboot_aout_symbol_table_t; 134 | 135 | /* The section header table for ELF. */ 136 | struct multiboot_elf_section_header_table 137 | { 138 | uint32_t num; 139 | uint32_t size; 140 | uint32_t addr; 141 | uint32_t shndx; 142 | }; 143 | typedef struct multiboot_elf_section_header_table multiboot_elf_section_header_table_t; 144 | 145 | struct multiboot_info 146 | { 147 | /* Multiboot info version number */ 148 | uint32_t flags; 149 | 150 | /* Available memory from BIOS */ 151 | uint32_t mem_lower; 152 | uint32_t mem_upper; 153 | 154 | /* "root" partition */ 155 | uint32_t boot_device; 156 | 157 | /* Kernel command line */ 158 | uint32_t cmdline; 159 | 160 | /* Boot-Module list */ 161 | uint32_t mods_count; 162 | uint32_t mods_addr; 163 | 164 | union 165 | { 166 | multiboot_aout_symbol_table_t aout_sym; 167 | multiboot_elf_section_header_table_t elf_sec; 168 | } u; 169 | 170 | /* Memory Mapping buffer */ 171 | uint32_t mmap_length; 172 | uint32_t mmap_addr; 173 | 174 | /* Drive Info buffer */ 175 | uint32_t drives_length; 176 | uint32_t drives_addr; 177 | 178 | /* ROM configuration table */ 179 | uint32_t config_table; 180 | 181 | /* Boot Loader Name */ 182 | uint32_t boot_loader_name; 183 | 184 | /* APM table */ 185 | uint32_t apm_table; 186 | 187 | /* Video */ 188 | uint32_t vbe_control_info; 189 | uint32_t vbe_mode_info; 190 | uint16_t vbe_mode; 191 | uint16_t vbe_interface_seg; 192 | uint16_t vbe_interface_off; 193 | uint16_t vbe_interface_len; 194 | }; 195 | typedef struct multiboot_info multiboot_info_t; 196 | 197 | struct multiboot_mmap_entry 198 | { 199 | uint32_t size; 200 | uint64_t addr; 201 | uint64_t len; 202 | #define MULTIBOOT_MEMORY_AVAILABLE 1 203 | #define MULTIBOOT_MEMORY_RESERVED 2 204 | uint32_t type; 205 | }__attribute__((packed)); 206 | typedef struct multiboot_mmap_entry multiboot_memory_map_t; 207 | 208 | struct multiboot_mod_list 209 | { 210 | /* the memory used goes from bytes 'mod_start' to 'mod_end-1' inclusive */ 211 | uint32_t mod_start; 212 | uint32_t mod_end; 213 | 214 | /* Module command line */ 215 | uint32_t cmdline; 216 | 217 | /* padding to take it to 16 bytes (must be zero) */ 218 | uint32_t pad; 219 | }__attribute__((packed)); 220 | typedef struct multiboot_mod_list multiboot_module_t; 221 | 222 | #endif /* ! ASM_FILE */ 223 | 224 | #endif /* ! MULTIBOOT_HEADER */ 225 | -------------------------------------------------------------------------------- /kernel/include/pipe.h: -------------------------------------------------------------------------------- 1 | #ifndef _PIPE_H 2 | #define _PIPE_H 3 | 4 | extern fs_t pipefs; 5 | 6 | #endif 7 | -------------------------------------------------------------------------------- /kernel/include/pit.h: -------------------------------------------------------------------------------- 1 | #ifndef _PIT_H 2 | #define _PIT_H 3 | 4 | void pit_set_freq(uint32_t hz); 5 | void pit_install(); 6 | 7 | extern uint32_t ticks; 8 | extern uint32_t sub_ticks; 9 | extern uint32_t pit_freq; 10 | extern uint32_t sub_tick_us; 11 | 12 | #endif 13 | -------------------------------------------------------------------------------- /kernel/include/process.h: -------------------------------------------------------------------------------- 1 | #ifndef _PROCESS_H 2 | #define _PROCESS_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #define USER_STACK 0x7FC0000000 11 | #define USER_STACK_SIZE 8192 * 1024 12 | 13 | typedef struct 14 | { 15 | uint64_t 16 | r15, r14, r13, r12, r11, r10, r9, r8, 17 | rdi, rsi, rbp, rbx, rcx, rdx, rax, 18 | rip, cs, rflags, rsp, ss; 19 | /* 20 | uint64_t 21 | r15, r14, r13, r12, r11, r10, r9, r8, 22 | rdi, rsi, rbp, rbx, rcx, rdx, rax, 23 | rip, rflags, rsp;*/ 24 | } __attribute__((packed)) stat_t; 25 | 26 | typedef struct 27 | { 28 | inode_t *inode; 29 | uint32_t offset; 30 | }process_file_t; 31 | 32 | typedef struct 33 | { 34 | uint32_t len; 35 | uint32_t max_len; 36 | process_file_t *ent; 37 | } file_list_t; 38 | 39 | typedef enum 40 | { 41 | READY, 42 | WAITING, 43 | //WAITING_CHILD, 44 | }process_status_t; 45 | 46 | typedef struct signal_queue_t 47 | { 48 | signal_num_t signum; 49 | struct signal_queue_t *next; 50 | }signal_queue_t; 51 | 52 | typedef struct process_struct process_t; 53 | typedef struct process_struct 54 | { 55 | uint8_t *name; 56 | uint32_t pid; 57 | file_list_t fds; 58 | uint64_t pdpt; 59 | uint64_t addr; // Address at which text section is loaded 60 | uint64_t size; // Actuall allocated memory 61 | uint64_t heap; 62 | process_t *parent; 63 | stat_t stat; 64 | void *fstat; // FPU state if avilable 65 | uint8_t *cwd; // Current working directory 66 | process_status_t status; 67 | 68 | struct sigaction handlers[21]; 69 | signal_queue_t *sigqueue; 70 | 71 | uint32_t ticks; 72 | uint32_t sub_ticks; 73 | uint32_t wait_us; 74 | 75 | uint8_t *args; //arguments seperated by null characters and double null-terminated 76 | uint8_t *envs; //same as arguments 77 | uint32_t argslen; 78 | uint32_t envslen; 79 | 80 | // used for procsses queue 81 | process_t *prev; 82 | process_t *next; 83 | } __attribute__((packed)) process_t; 84 | 85 | void map_mem_user(uint64_t pdpt, uint64_t *ptr, uint32_t size); 86 | 87 | extern process_t *current_process; 88 | void fork_process(process_t*); 89 | extern uint32_t forking; 90 | extern uint32_t fork_skip_page; 91 | 92 | extern void switch_context(stat_t*); 93 | 94 | process_t *load_elf(char*); 95 | void exit_process(process_t*); 96 | void exec_process(uint8_t *path, uint8_t **arg, uint8_t **env); 97 | 98 | uint32_t get_fd(process_t*); 99 | process_t *process_by_pid(pid_t pid); 100 | 101 | void signal_raise(process_t *p, signal_num_t signal); 102 | uint32_t validate(process_t *, void *); 103 | #endif 104 | -------------------------------------------------------------------------------- /kernel/include/scheduler.h: -------------------------------------------------------------------------------- 1 | #ifndef _SCHEDULER_H 2 | #define _SCHEDULER_H 3 | 4 | 5 | 6 | #endif 7 | -------------------------------------------------------------------------------- /kernel/include/serial.h: -------------------------------------------------------------------------------- 1 | #ifndef _SERIAL_H 2 | #define _SERIAL_H 3 | 4 | #define COM1 0x3F8 5 | 6 | typedef struct { 7 | void (*init) (); 8 | void (*write) (uint8_t); 9 | void (*write_str) (uint8_t*); 10 | void (*end)(); 11 | } serial_t; 12 | 13 | serial_t serial; 14 | 15 | #endif 16 | -------------------------------------------------------------------------------- /kernel/include/signal.h: -------------------------------------------------------------------------------- 1 | #ifndef _SIGNAL_H 2 | #define _SIGNAL_H 3 | 4 | #include 5 | //#include 6 | 7 | //Ignore 8 | #define IGN 0 9 | //Terminate 10 | #define TRM 1 11 | //Stop 12 | #define STP 2 13 | //Continue 14 | #define CNT 3 15 | 16 | typedef enum 17 | { 18 | SIGHUP = 1, 19 | SIGINT = 2, 20 | SIGQUIT = 3, 21 | SIGILL = 4, 22 | SIGTRAP = 5, 23 | SIGABRT = 6, 24 | SIGBUS = 7, 25 | SIGFPE = 8, 26 | SIGKILL = 9, 27 | SIGUSR1 = 10, 28 | SIGSEGV = 11, 29 | SIGUSR2 = 12, 30 | SIGPIPE = 13, 31 | SIGALRM = 14, 32 | __UNUSED__, 33 | SIGCHLD = 16, 34 | SIGCONT = 17, 35 | SIGSTOP = 18, 36 | SIGTSTP = 19, 37 | SIGTTIN = 20, 38 | SIGTTOU = 21, 39 | } signal_num_t; 40 | 41 | extern int signal_default_action[]; 42 | //extern char *signal_names[]; 43 | 44 | #endif 45 | -------------------------------------------------------------------------------- /kernel/include/string.h: -------------------------------------------------------------------------------- 1 | #ifndef _STRING_H 2 | #define _STRING_H 3 | 4 | #include 5 | 6 | uint32_t strlen(uint8_t*); 7 | uint8_t *strdup(uint8_t*); 8 | uint32_t strcmp(uint8_t*, uint8_t*); 9 | uint8_t *strcat(uint8_t*, uint8_t*); 10 | uint8_t *itoa(uint32_t); 11 | void *memset(void*, uint8_t, uint32_t); 12 | uint8_t *strndup(uint8_t*, uint32_t); 13 | uint32_t isdigit(uint8_t); 14 | uint32_t isalpha(uint8_t); 15 | uint32_t within(uint8_t, uint8_t*); 16 | 17 | #endif 18 | -------------------------------------------------------------------------------- /kernel/include/sys/types.h: -------------------------------------------------------------------------------- 1 | #ifndef _TYPES_H 2 | #define _TYPES_H 3 | 4 | typedef uint32_t pid_t; 5 | 6 | struct sigaction 7 | { 8 | void (*sa_handler)(int); 9 | //void (*sa_sigaction)(int, siginfo_t *, void *); 10 | //sigset_t sa_mask; 11 | int sa_flags; 12 | }; 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /kernel/include/syscall.h: -------------------------------------------------------------------------------- 1 | #ifndef _SYSCALL_H 2 | #define _SYSCALL_H 3 | 4 | #define SYS(f) void f(uint64_t rbx, uint64_t rcx, uint64_t rdx) 5 | 6 | extern void* sys_calls[]; 7 | 8 | #define sys_calls_count sizeof(sys_calls)/0x8 9 | 10 | #endif 11 | -------------------------------------------------------------------------------- /kernel/include/system.h: -------------------------------------------------------------------------------- 1 | #ifndef _SYSTEM_H 2 | #define _SYSTEM_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #define NULL ((void*)0) 9 | #define MIN(a, b) ((ab)?a:b) 11 | 12 | #if _DEBUG_ > 0 13 | #define assert(level, var, msg) \ 14 | do{ \ 15 | if(!var) \ 16 | debug("%s @%s[%d] : '%s' %s\n", __FILE__, __FUNCTION__, \ 17 | __LINE__, #var, msg); \ 18 | if(level) for(;;); \ 19 | }while(0); 20 | #else 21 | #define assert(level, var, msg) 22 | #endif 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /kernel/include/tty.h: -------------------------------------------------------------------------------- 1 | #ifndef _TTY_H 2 | #define _TTY_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | typedef struct tty_master_device_struct tty_master_t; 9 | typedef struct tty_device_struct tty_device_t; 10 | 11 | #include 12 | 13 | struct tty_master_device_struct 14 | { 15 | uint32_t cur_tty; //Currently active tty 16 | 17 | void (*invoke)(tty_device_t *tty, uint32_t req, ...); 18 | // Methods for console or terminal emulator 19 | inode_t *console; 20 | }; 21 | 22 | struct tty_device_struct 23 | { 24 | uint32_t id; 25 | tty_master_t *master; 26 | //uint8_t *ptr; // tty buffer 27 | uint32_t pos; 28 | virtcon_device_t *virtcon; 29 | 30 | // TODO : add process group id member so every tty can be assigned to one group 31 | process_t *p; // Process currently reading from TTY 32 | uint8_t *buf; // The buffer of the currently reading process 33 | uint64_t len; // Currently reading process buffer length 34 | }; 35 | 36 | void ttym_invoke(tty_device_t *tty, uint32_t req, ...); 37 | typedef enum 38 | { 39 | TTYM_WRITE, 40 | TTYM_SWITCH, 41 | }ttym_requests; 42 | 43 | dev_t ttydev; 44 | 45 | extern inode_t *cur_tty; 46 | 47 | #endif 48 | -------------------------------------------------------------------------------- /kernel/include/utypes.h: -------------------------------------------------------------------------------- 1 | #ifndef _UTYPES_H 2 | #define _UTYPES_H 3 | 4 | typedef unsigned char uint8_t; 5 | typedef unsigned short uint16_t; 6 | typedef unsigned int uint32_t; 7 | typedef unsigned long long uint64_t; 8 | 9 | #endif 10 | -------------------------------------------------------------------------------- /kernel/include/va_list.h: -------------------------------------------------------------------------------- 1 | #ifndef _VA_LIST_H 2 | #define _VA_LIST_H 3 | 4 | typedef __builtin_va_list va_list; 5 | #define va_start(ap,last) __builtin_va_start(ap, last) 6 | #define va_end(ap) __builtin_va_end(ap) 7 | #define va_arg(ap,type) __builtin_va_arg(ap,type) 8 | #define va_copy(dest, src) __builtin_va_copy(dest,src) 9 | 10 | #endif 11 | -------------------------------------------------------------------------------- /kernel/include/vbe.h: -------------------------------------------------------------------------------- 1 | #ifndef VBE_H 2 | #define VBE_H 3 | 4 | #include 5 | 6 | // This file is from virtualbox.org 7 | 8 | // DISPI helper function 9 | //void dispi_set_enable(Boolean enable); 10 | 11 | /** VBE int10 API 12 | * 13 | * See the function descriptions in vbe.c for more information 14 | */ 15 | 16 | /* Far pointer for VBE info block usage. */ 17 | typedef union vbe_ptr { 18 | uint32_t Ptr32; 19 | //void __far *Ptr; 20 | union { 21 | uint16_t Off; 22 | uint16_t Seg; 23 | }; 24 | } vbe_ptr; 25 | 26 | // The official VBE Information Block 27 | typedef struct VbeInfoBlock 28 | { 29 | union { 30 | uint8_t SigChr[4]; 31 | uint32_t Sig32; 32 | } VbeSignature; 33 | uint16_t VbeVersion; 34 | vbe_ptr OemString; 35 | uint8_t Capabilities[4]; 36 | uint16_t VideoModePtr_Off; 37 | uint16_t VideoModePtr_Seg; 38 | uint16_t TotalMemory; 39 | uint16_t OemSoftwareRev; 40 | vbe_ptr OemVendorName; 41 | vbe_ptr OemProductName; 42 | vbe_ptr OemProductRev; 43 | uint16_t Reserved[111]; // used for dynamically generated mode list 44 | uint8_t OemData[256]; 45 | } VbeInfoBlock; 46 | 47 | 48 | // This one is for compactly storing a static list of mode info blocks 49 | // this saves us 189 bytes per block 50 | typedef struct ModeInfoBlockCompact 51 | { 52 | // Mandatory information for all VBE revisions 53 | uint16_t ModeAttributes; 54 | uint8_t WinAAttributes; 55 | uint8_t WinBAttributes; 56 | uint16_t WinGranularity; 57 | uint16_t WinSize; 58 | uint16_t WinASegment; 59 | uint16_t WinBSegment; 60 | uint32_t WinFuncPtr; 61 | uint16_t BytesPerScanLine; 62 | // Mandatory information for VBE 1.2 and above 63 | uint16_t XResolution; 64 | uint16_t YResolution; 65 | uint8_t XCharSize; 66 | uint8_t YCharSize; 67 | uint8_t NumberOfPlanes; 68 | uint8_t BitsPerPixel; 69 | uint8_t NumberOfBanks; 70 | uint8_t MemoryModel; 71 | uint8_t BankSize; 72 | uint8_t NumberOfImagePages; 73 | uint8_t Reserved_page; 74 | // Direct Color fields (required for direct/6 and YUV/7 memory models) 75 | uint8_t RedMaskSize; 76 | uint8_t RedFieldPosition; 77 | uint8_t GreenMaskSize; 78 | uint8_t GreenFieldPosition; 79 | uint8_t BlueMaskSize; 80 | uint8_t BlueFieldPosition; 81 | uint8_t RsvdMaskSize; 82 | uint8_t RsvdFieldPosition; 83 | uint8_t DirectColorModeInfo; 84 | // Mandatory information for VBE 2.0 and above 85 | uint32_t PhysBasePtr; 86 | uint32_t OffScreenMemOffset; 87 | uint16_t OffScreenMemSize; 88 | // Mandatory information for VBE 3.0 and above 89 | uint16_t LinBytesPerScanLine; 90 | uint8_t BnkNumberOfPages; 91 | uint8_t LinNumberOfPages; 92 | uint8_t LinRedMaskSize; 93 | uint8_t LinRedFieldPosition; 94 | uint8_t LinGreenMaskSize; 95 | uint8_t LinGreenFieldPosition; 96 | uint8_t LinBlueMaskSize; 97 | uint8_t LinBlueFieldPosition; 98 | uint8_t LinRsvdMaskSize; 99 | uint8_t LinRsvdFieldPosition; 100 | uint32_t MaxPixelClock; 101 | // uint8_t Reserved[189]; // DO NOT PUT THIS IN HERE because of Compact Mode Info storage in bios 102 | } __attribute__((packed)) ModeInfoBlockCompact; 103 | 104 | typedef struct ModeInfoBlock 105 | { 106 | // Mandatory information for all VBE revisions 107 | uint16_t ModeAttributes; 108 | uint8_t WinAAttributes; 109 | uint8_t WinBAttributes; 110 | uint16_t WinGranularity; 111 | uint16_t WinSize; 112 | uint16_t WinASegment; 113 | uint16_t WinBSegment; 114 | uint32_t WinFuncPtr; 115 | uint16_t BytesPerScanLine; 116 | // Mandatory information for VBE 1.2 and above 117 | uint16_t XResolution; 118 | uint16_t YResolution; 119 | uint8_t XCharSize; 120 | uint8_t YCharSize; 121 | uint8_t NumberOfPlanes; 122 | uint8_t BitsPerPixel; 123 | uint8_t NumberOfBanks; 124 | uint8_t MemoryModel; 125 | uint8_t BankSize; 126 | uint8_t NumberOfImagePages; 127 | uint8_t Reserved_page; 128 | // Direct Color fields (required for direct/6 and YUV/7 memory models) 129 | uint8_t RedMaskSize; 130 | uint8_t RedFieldPosition; 131 | uint8_t GreenMaskSize; 132 | uint8_t GreenFieldPosition; 133 | uint8_t BlueMaskSize; 134 | uint8_t BlueFieldPosition; 135 | uint8_t RsvdMaskSize; 136 | uint8_t RsvdFieldPosition; 137 | uint8_t DirectColorModeInfo; 138 | // Mandatory information for VBE 2.0 and above 139 | uint32_t PhysBasePtr; 140 | uint32_t OffScreenMemOffset; 141 | uint16_t OffScreenMemSize; 142 | // Mandatory information for VBE 3.0 and above 143 | uint16_t LinBytesPerScanLine; 144 | uint8_t BnkNumberOfPages; 145 | uint8_t LinNumberOfPages; 146 | uint8_t LinRedMaskSize; 147 | uint8_t LinRedFieldPosition; 148 | uint8_t LinGreenMaskSize; 149 | uint8_t LinGreenFieldPosition; 150 | uint8_t LinBlueMaskSize; 151 | uint8_t LinBlueFieldPosition; 152 | uint8_t LinRsvdMaskSize; 153 | uint8_t LinRsvdFieldPosition; 154 | uint32_t MaxPixelClock; 155 | uint8_t Reserved[189]; 156 | } ModeInfoBlock; 157 | 158 | typedef struct ModeInfoListItem 159 | { 160 | uint16_t mode; 161 | ModeInfoBlockCompact info; 162 | } ModeInfoListItem; 163 | 164 | // VBE Return Status Info 165 | // AL 166 | #define VBE_RETURN_STATUS_SUPPORTED 0x4F 167 | #define VBE_RETURN_STATUS_UNSUPPORTED 0x00 168 | // AH 169 | #define VBE_RETURN_STATUS_SUCCESSFULL 0x00 170 | #define VBE_RETURN_STATUS_FAILED 0x01 171 | #define VBE_RETURN_STATUS_NOT_SUPPORTED 0x02 172 | #define VBE_RETURN_STATUS_INVALID 0x03 173 | 174 | // VBE Mode Numbers 175 | 176 | #define VBE_MODE_VESA_DEFINED 0x0100 177 | #define VBE_MODE_REFRESH_RATE_USE_CRTC 0x0800 178 | #define VBE_MODE_LINEAR_FRAME_BUFFER 0x4000 179 | #define VBE_MODE_PRESERVE_DISPLAY_MEMORY 0x8000 180 | 181 | // VBE GFX Mode Number 182 | 183 | #define VBE_VESA_MODE_640X400X8 0x100 184 | #define VBE_VESA_MODE_640X480X8 0x101 185 | #define VBE_VESA_MODE_800X600X4 0x102 186 | #define VBE_VESA_MODE_800X600X8 0x103 187 | #define VBE_VESA_MODE_1024X768X4 0x104 188 | #define VBE_VESA_MODE_1024X768X8 0x105 189 | #define VBE_VESA_MODE_1280X1024X4 0x106 190 | #define VBE_VESA_MODE_1280X1024X8 0x107 191 | #define VBE_VESA_MODE_320X200X1555 0x10D 192 | #define VBE_VESA_MODE_320X200X565 0x10E 193 | #define VBE_VESA_MODE_320X200X888 0x10F 194 | #define VBE_VESA_MODE_640X480X1555 0x110 195 | #define VBE_VESA_MODE_640X480X565 0x111 196 | #define VBE_VESA_MODE_640X480X888 0x112 197 | #define VBE_VESA_MODE_800X600X1555 0x113 198 | #define VBE_VESA_MODE_800X600X565 0x114 199 | #define VBE_VESA_MODE_800X600X888 0x115 200 | #define VBE_VESA_MODE_1024X768X1555 0x116 201 | #define VBE_VESA_MODE_1024X768X565 0x117 202 | #define VBE_VESA_MODE_1024X768X888 0x118 203 | #define VBE_VESA_MODE_1280X1024X1555 0x119 204 | #define VBE_VESA_MODE_1280X1024X565 0x11A 205 | #define VBE_VESA_MODE_1280X1024X888 0x11B 206 | #define VBE_VESA_MODE_1600X1200X8 0x11C 207 | #define VBE_VESA_MODE_1600X1200X1555 0x11D 208 | #define VBE_VESA_MODE_1600X1200X565 0x11E 209 | #define VBE_VESA_MODE_1600X1200X888 0x11F 210 | 211 | // BOCHS/PLEX86 'own' mode numbers 212 | #define VBE_OWN_MODE_320X200X8888 0x140 213 | #define VBE_OWN_MODE_640X400X8888 0x141 214 | #define VBE_OWN_MODE_640X480X8888 0x142 215 | #define VBE_OWN_MODE_800X600X8888 0x143 216 | #define VBE_OWN_MODE_1024X768X8888 0x144 217 | #define VBE_OWN_MODE_1280X1024X8888 0x145 218 | #define VBE_OWN_MODE_320X200X8 0x146 219 | #define VBE_OWN_MODE_1600X1200X8888 0x147 220 | #define VBE_OWN_MODE_1152X864X8 0x148 221 | #define VBE_OWN_MODE_1152X864X1555 0x149 222 | #define VBE_OWN_MODE_1152X864X565 0x14a 223 | #define VBE_OWN_MODE_1152X864X888 0x14b 224 | #define VBE_OWN_MODE_1152X864X8888 0x14c 225 | 226 | #define VBE_VESA_MODE_END_OF_LIST 0xFFFF 227 | 228 | // Capabilities 229 | 230 | #define VBE_CAPABILITY_8BIT_DAC 0x0001 231 | #define VBE_CAPABILITY_NOT_VGA_COMPATIBLE 0x0002 232 | #define VBE_CAPABILITY_RAMDAC_USE_BLANK_BIT 0x0004 233 | #define VBE_CAPABILITY_STEREOSCOPIC_SUPPORT 0x0008 234 | #define VBE_CAPABILITY_STEREO_VIA_VESA_EVC 0x0010 235 | 236 | // Mode Attributes 237 | 238 | #define VBE_MODE_ATTRIBUTE_SUPPORTED 0x0001 239 | #define VBE_MODE_ATTRIBUTE_EXTENDED_INFORMATION_AVAILABLE 0x0002 240 | #define VBE_MODE_ATTRIBUTE_TTY_BIOS_SUPPORT 0x0004 241 | #define VBE_MODE_ATTRIBUTE_COLOR_MODE 0x0008 242 | #define VBE_MODE_ATTRIBUTE_GRAPHICS_MODE 0x0010 243 | #define VBE_MODE_ATTRIBUTE_NOT_VGA_COMPATIBLE 0x0020 244 | #define VBE_MODE_ATTRIBUTE_NO_VGA_COMPATIBLE_WINDOW 0x0040 245 | #define VBE_MODE_ATTRIBUTE_LINEAR_FRAME_BUFFER_MODE 0x0080 246 | #define VBE_MODE_ATTRIBUTE_DOUBLE_SCAN_MODE 0x0100 247 | #define VBE_MODE_ATTRIBUTE_INTERLACE_MODE 0x0200 248 | #define VBE_MODE_ATTRIBUTE_HARDWARE_TRIPLE_BUFFER 0x0400 249 | #define VBE_MODE_ATTRIBUTE_HARDWARE_STEREOSCOPIC_DISPLAY 0x0800 250 | #define VBE_MODE_ATTRIBUTE_DUAL_DISPLAY_START_ADDRESS 0x1000 251 | 252 | #define VBE_MODE_ATTTRIBUTE_LFB_ONLY ( VBE_MODE_ATTRIBUTE_NO_VGA_COMPATIBLE_WINDOW | VBE_MODE_ATTRIBUTE_LINEAR_FRAME_BUFFER_MODE ) 253 | 254 | // Window attributes 255 | 256 | #define VBE_WINDOW_ATTRIBUTE_RELOCATABLE 0x01 257 | #define VBE_WINDOW_ATTRIBUTE_READABLE 0x02 258 | #define VBE_WINDOW_ATTRIBUTE_WRITEABLE 0x04 259 | 260 | // Memory model 261 | 262 | #define VBE_MEMORYMODEL_TEXT_MODE 0x00 263 | #define VBE_MEMORYMODEL_CGA_GRAPHICS 0x01 264 | #define VBE_MEMORYMODEL_HERCULES_GRAPHICS 0x02 265 | #define VBE_MEMORYMODEL_PLANAR 0x03 266 | #define VBE_MEMORYMODEL_PACKED_PIXEL 0x04 267 | #define VBE_MEMORYMODEL_NON_CHAIN_4_256 0x05 268 | #define VBE_MEMORYMODEL_DIRECT_COLOR 0x06 269 | #define VBE_MEMORYMODEL_YUV 0x07 270 | 271 | // DirectColorModeInfo 272 | 273 | #define VBE_DIRECTCOLOR_COLOR_RAMP_PROGRAMMABLE 0x01 274 | #define VBE_DIRECTCOLOR_RESERVED_BITS_AVAILABLE 0x02 275 | 276 | /** 277 | * VBE Bios Extra Data structure. 278 | * @remark duplicated in DevVGA.h. 279 | */ 280 | typedef struct VBEHeader 281 | { 282 | /** Signature (VBEHEADER_MAGIC). */ 283 | uint16_t uint16_tSignature; 284 | /** Data size. */ 285 | uint16_t cbData; 286 | } VBEHeader; 287 | 288 | /** The value of the VBEHEADER::uint16_tSignature field. 289 | * @remark duplicated in DevVGA.h. */ 290 | #define VBEHEADER_MAGIC 0x77CC 291 | 292 | /** The extra port which is used to read the mode list. 293 | * @remark duplicated in DevVGA.h. */ 294 | #define VBE_EXTRA_PORT 0x3b6 295 | 296 | /** The extra port which is used for debug printf. 297 | * @remark duplicated in DevVGA.h. */ 298 | #define VBE_PRINTF_PORT 0x3b7 299 | 300 | #endif 301 | -------------------------------------------------------------------------------- /kernel/include/vfs.h: -------------------------------------------------------------------------------- 1 | #ifndef _VFS_H 2 | #define _VFS_H 3 | 4 | #include 5 | 6 | typedef struct filesystem_struct fs_t; 7 | typedef enum { FS_FILE, FS_DIR, FS_CHRDEV, FS_BLKDEV, FS_SYMLINK, FS_PIPE, FS_MOUNTPOINT } inode_type; 8 | typedef struct inode_struct inode_t; 9 | typedef struct dentry_struct dentry_t; 10 | 11 | typedef struct filesystem_struct 12 | { 13 | uint8_t *name; 14 | inode_t* (*load) (inode_t*); 15 | uint32_t (*link) (inode_t*, uint8_t*); 16 | uint32_t (*unlink)(inode_t*, uint8_t*); 17 | uint64_t (*read) (inode_t*, uint64_t, uint64_t, void*); 18 | uint64_t (*write) (inode_t*, uint64_t, uint64_t, void*); 19 | uint32_t (*ioctl) (inode_t*, uint64_t, ...); 20 | uint32_t (*mount) (inode_t*, inode_t*); 21 | }fs_t; 22 | 23 | #include 24 | 25 | struct inode_struct 26 | { 27 | uint8_t *name; 28 | uint32_t size; 29 | inode_type type; 30 | inode_t *parent; 31 | dentry_t *list; 32 | fs_t *fs; 33 | dev_t *dev; 34 | void *p; // To be used by filesystem handler 35 | 36 | inode_t *next; // For directories 37 | }; 38 | 39 | struct dentry_struct 40 | { 41 | uint32_t count; 42 | inode_t *head; 43 | }; 44 | 45 | typedef struct vfs_mountpoint_struct 46 | { 47 | inode_t *inode; 48 | inode_t *old_inode; 49 | }vfs_mountpoint_t; 50 | 51 | typedef struct dirent { 52 | uint32_t d_ino; 53 | char d_name[256]; 54 | } dirent; 55 | 56 | typedef struct 57 | { 58 | void (*init) (); 59 | fs_t * (*getfs)(uint8_t *name); 60 | } fsman_t; 61 | 62 | extern fsman_t fsman; 63 | 64 | extern fs_t vfs; 65 | 66 | extern inode_t *vfs_root; 67 | inode_t *vfs_trace_path(inode_t*, uint8_t*); 68 | inode_t *vfs_create(inode_t*, uint8_t*, inode_t*); 69 | inode_t *vfs_mount(inode_t*, uint8_t*, inode_t*); 70 | void vfs_tree(inode_t*); 71 | 72 | uint64_t vfs_read (inode_t*, uint64_t, uint64_t, void*); 73 | uint64_t vfs_write(inode_t*, uint64_t, uint64_t, void*); 74 | 75 | #endif 76 | -------------------------------------------------------------------------------- /kernel/kernel.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | void map_mem(multiboot_info_t*); 24 | 25 | uint8_t *vga = (uint8_t*)0xA0000000000; 26 | void init_video() 27 | {/* 28 | VbeInfoBlock *vbe_info = (VbeInfoBlock*)(uint64_t)mboot_info->vbe_control_info; 29 | ModeInfoBlock *vbe = (ModeInfoBlock*)(uint64_t)(mboot_info->vbe_mode_info); 30 | debug("Resolution %dx%d\n", vbe->XResolution, vbe->YResolution); 31 | debug("VBE V:%d.%d #0x%x [%d]\n", vbe_info->VbeVersion >> 2*4, 32 | vbe_info->VbeVersion & 0xF , vbe->PhysBasePtr, vbe->LinBytesPerScanLine); 33 | 34 | mman.set_unusable(vbe->PhysBasePtr, 2*1024*1024); 35 | uint64_t *vga_pdpt = (uint64_t*)mman.get_frame(); 36 | uint64_t *vga_pd = (uint64_t*)mman.get_frame(); 37 | uint64_t *vga_pt = (uint64_t*)mman.get_frame(); 38 | 39 | uint64_t i = vbe->PhysBasePtr - 4*1024, k = 0; 40 | while( k < 512 ) // 2 MiB 41 | vga_pt[k++] = (uint64_t)(i += 4*1024) | 3; 42 | *vga_pd = (uint64_t)vga_pt | 3; 43 | *vga_pdpt = (uint64_t)vga_pd | 3; 44 | *(PML4 + 20) = (uint64_t)vga_pdpt | 3; // 0xA0000000000 45 | 46 | TLB_flush();*/ 47 | } 48 | 49 | void kmain(void) 50 | { 51 | kernel_end = (uint64_t)heap_addr; 52 | kernel_heap_ptr = (uint8_t*)((uint64_t)&VMA + kernel_end + heap_size) ; 53 | UPD = (uint64_t*)((uint64_t)&VMA + kernel_end + 0x3000); 54 | KPD = (uint64_t*)((uint64_t)&VMA + kernel_end + 0x4000); 55 | PML4 = (uint64_t*)((uint64_t)&VMA + kernel_end); 56 | *(KPD + 511) = (kernel_end + 0x4000) | 3; 57 | map_mem(mboot_info); 58 | 59 | #if _GFX_ 60 | init_video(); 61 | #endif 62 | 63 | idt_install(); 64 | isr_install(); 65 | 66 | vmem_init(); 67 | 68 | serial.init(); 69 | 70 | extern void load_tss(void); 71 | load_tss(); 72 | extern uint64_t k_tss64_sp; 73 | *(uint64_t*)( (uint64_t)&VMA + (uint64_t)&k_tss64_sp ) = 0xFFFFFFFFC0008000; 74 | 75 | pit_set_freq(2000); // timer tick = 500 us 76 | pit_install(); 77 | irq_install(); 78 | 79 | extern void mouse_init(); 80 | //mouse_init(); 81 | extern void mouse_handler(void*); 82 | //irq_install_handler(12, mouse_handler); 83 | 84 | multiboot_module_t *mod = (multiboot_module_t*)(uint64_t)mboot_info->mods_addr; 85 | 86 | ramdev_private_t ramdev_private = 87 | (ramdev_private_t) 88 | { 89 | .ptr = (void*)((uint64_t)&VMA + mod->mod_start), 90 | .size = (uint32_t)(mod->mod_end - mod->mod_start), 91 | }; 92 | 93 | inode_t ramdisk_inode = 94 | (inode_t) 95 | { 96 | .name = "ramdisk", 97 | .type = FS_CHRDEV, 98 | .fs = &devfs, 99 | .dev = &ramdev, 100 | .p = &ramdev_private, 101 | }; 102 | 103 | vfs_create(&dev_root, "/", &ramdisk_inode); 104 | 105 | inode_t *rootfs = initramfs.load(&ramdisk_inode); 106 | 107 | vfs_mount_root(rootfs); 108 | 109 | irq_install_handler(1, kbd_handler); 110 | 111 | devman.init(); 112 | fsman.init(); 113 | 114 | #if _DBG_CON_ 115 | // We should disable debugging by this stage! 116 | serial.end(); 117 | #endif 118 | 119 | process_t *init = load_elf("/bin/init"); 120 | 121 | extern void spawn_init(process_t*); 122 | spawn_init(init); 123 | for(;;); 124 | } 125 | -------------------------------------------------------------------------------- /kernel/link.ld: -------------------------------------------------------------------------------- 1 | OUTPUT_FORMAT(elf64-x86-64) 2 | ENTRY(_start) 3 | 4 | SECTIONS { 5 | 6 | PMA = 0x100000; 7 | . = PMA; 8 | 9 | .boot.text ALIGN(0x1000) : { 10 | boot.o(.text) 11 | /*boot.o(.rodata*)*/ 12 | } 13 | 14 | .boot.data ALIGN(0x1000) : { 15 | boot.o(.data) 16 | } 17 | 18 | .boot.bss ALIGN(0x1000) : { 19 | boot.o(.bss) 20 | } 21 | 22 | VMA = 0xFFFFFFFFC0000000; 23 | . += VMA; 24 | 25 | kstart = . - VMA; 26 | 27 | .text ALIGN(0x1000) : AT(ADDR(.text) - VMA) { 28 | *(EXCLUDE_FILE(boot.o).text) 29 | *(.rodata*) 30 | } 31 | 32 | kstart_ = ADDR(.text); 33 | .data ALIGN(0x1000) : AT(ADDR(.data) - VMA) { 34 | *(EXCLUDE_FILE(*boot.o).data) 35 | } 36 | 37 | .bss ALIGN(0x1000) : AT(ADDR(.bss) - VMA) { 38 | *(EXCLUDE_FILE(*boot.o).bss) 39 | } 40 | 41 | 42 | kend = . - VMA; 43 | } 44 | -------------------------------------------------------------------------------- /kernel/mem/Makefile: -------------------------------------------------------------------------------- 1 | 2 | include ../Makefile.cfg 3 | 4 | OBJ = kmem.o 5 | OUT=../obj 6 | 7 | CFLAGS = -c -I ../include/ -mcmodel=large -nostdlib -ffreestanding 8 | 9 | all: $(OBJ) 10 | ${CP} $(OBJ) $(OUT) 11 | 12 | $(OUT)/%.o: %.c 13 | $(CC) $(CFLAGS) $< -o $@ 14 | 15 | clean: 16 | ${RM} -f $(OBJ) 17 | 18 | -------------------------------------------------------------------------------- /kernel/misc/Makefile: -------------------------------------------------------------------------------- 1 | 2 | include ../Makefile.cfg 3 | 4 | OBJ = io.o serial.o debug.o string.o 5 | OUT=../obj 6 | 7 | CFLAGS = -c -I ../include/ -mcmodel=large -nostdlib -ffreestanding 8 | 9 | all: $(OBJ) 10 | ${CP} $(OBJ) $(OUT) 11 | 12 | $(OUT)/%.o: %.c 13 | ${CC} $(CFLAGS) $< -o $@ 14 | 15 | clean: 16 | ${RM} -f $(OBJ) 17 | -------------------------------------------------------------------------------- /kernel/misc/debug.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #if _DEBUG_ > 0 7 | 8 | static void debugs(uint8_t *str) 9 | { 10 | serial.write_str(str); 11 | } 12 | 13 | static void debugx(uint32_t val) 14 | { 15 | uint8_t *enc = "0123456789ABCDEF"; 16 | uint8_t buf[9]; 17 | buf[8] = '\0'; 18 | uint8_t i = 8; 19 | while(i) 20 | { 21 | buf[--i] = enc[val&0xF]; 22 | val >>= 4; 23 | } 24 | debug(buf); 25 | } 26 | 27 | static void debuglx(uint64_t val) 28 | { 29 | uint8_t *enc = "0123456789ABCDEF"; 30 | uint8_t buf[17]; 31 | buf[16] = '\0'; 32 | uint8_t i = 16; 33 | while(i) 34 | { 35 | buf[--i] = enc[val&0xF]; 36 | val >>= 4; 37 | } 38 | debug(buf); 39 | } 40 | 41 | static void debugud(uint32_t val) 42 | { 43 | uint8_t buf[11]; 44 | buf[10] = '\0'; 45 | if(!val) { buf[9] = '0'; debug(&buf[9]); } 46 | uint8_t i = 10; 47 | while(val) 48 | { 49 | buf[--i] = val%10 + '0'; 50 | val = (val-val%10)/10; 51 | } 52 | debug(buf+i); 53 | } 54 | 55 | static void debugul(uint64_t val) 56 | { 57 | uint8_t buf[21]; 58 | buf[20] = '\0'; 59 | uint8_t i = 20; 60 | while(val) 61 | { 62 | buf[--i] = val%10 + '0'; 63 | val = (val-val%10)/10; 64 | } 65 | debug(buf+i); 66 | } 67 | 68 | static void debugb(uint8_t val) 69 | { 70 | uint8_t buf[9]; 71 | buf[8] = '\0'; 72 | uint8_t i = 8; 73 | while(i) 74 | { 75 | buf[--i] = '0' + (val & 1); 76 | val >>= 1; 77 | } 78 | debug(buf); 79 | } 80 | 81 | void debug(uint8_t *fmt, ...) 82 | { 83 | va_list args; 84 | va_start(args, fmt); 85 | 86 | while(*fmt) 87 | switch(*fmt) 88 | { 89 | case '%': 90 | ++fmt; 91 | switch(*fmt) 92 | { 93 | case 's': /* char * */ 94 | serial.write_str((uint8_t*)va_arg(args, uint8_t*)); 95 | break; 96 | case 'd': /* decimal */ 97 | debugud((uint32_t)va_arg(args, uint32_t)); 98 | break; 99 | case 'l': /* long */ 100 | switch(*++fmt) 101 | { 102 | case 'x': /* long hex */ 103 | debuglx((uint64_t)va_arg(args, uint64_t)); 104 | break; 105 | case 'd': 106 | debugul((uint64_t)va_arg(args, uint64_t)); 107 | break; 108 | default: 109 | serial.write(*--fmt); 110 | } 111 | break; 112 | 113 | case 'b': /* binary */ 114 | debugb((uint8_t)(uint32_t)va_arg(args, uint32_t)); 115 | break; 116 | case 'x': /* Hexadecimal */ 117 | debugx((uint32_t)va_arg(args, uint32_t)); 118 | break; 119 | default: 120 | serial.write(*(--fmt)); 121 | } 122 | ++fmt; 123 | break; 124 | case '\n': 125 | #if _DBG_CON_ 126 | serial.write('\n'); 127 | #else 128 | serial.write_str("\n\r"); 129 | #endif 130 | ++fmt; 131 | break; 132 | default: 133 | serial.write(*fmt); 134 | ++fmt; 135 | } 136 | va_end(args); 137 | } 138 | 139 | #endif 140 | -------------------------------------------------------------------------------- /kernel/misc/io.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | inline uint8_t inb(uint32_t port) 5 | { 6 | uint8_t ret; 7 | asm volatile ("inb %w1, %b0" : "=a"(ret) : "d"(port)); 8 | return ret; 9 | } 10 | 11 | inline void outb(uint32_t port, uint8_t val) 12 | { 13 | asm volatile ("outb %b0, %w1" : /* No Output */ : "a"(val), "d"(port)); 14 | } 15 | 16 | -------------------------------------------------------------------------------- /kernel/misc/serial.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | inode_t serial_tty; 9 | tty_device_t serial_tty_dev; 10 | 11 | static uint8_t serial_enabled = 0; 12 | 13 | static void init_com1() 14 | { 15 | #if _DBG_CON_ 16 | 17 | serial_tty_dev = 18 | (tty_device_t) 19 | { 20 | .id = 0, 21 | .master = NULL, 22 | .pos = 0, 23 | .virtcon = get_virtcon(&serial_tty_dev, 80, 25), 24 | .p = NULL, 25 | .buf = NULL, 26 | .len = 0, 27 | }; 28 | 29 | 30 | serial_tty = 31 | (inode_t) 32 | { 33 | .type = FS_CHRDEV, 34 | .fs = &devfs, 35 | .dev = &ttydev, 36 | .p = &serial_tty_dev, 37 | }; 38 | 39 | cur_tty = &serial_tty; 40 | #else 41 | outb(COM1 + 1, 0x00); // Disable all interrupts 42 | outb(COM1 + 3, 0x80); // Enable DLAB 43 | outb(COM1 + 0, 0x03); // Set divisor to 3 44 | outb(COM1 + 1, 0x00); 45 | outb(COM1 + 3, 0x03); // 8 bits, no parity, one stop bit 46 | outb(COM1 + 2, 0xC7); // Enable FIFO, clear it with 14-byte threshold 47 | outb(COM1 + 4, 0x0B); // IRQs enabled 48 | #endif 49 | serial_enabled = 1; 50 | } 51 | 52 | static uint8_t serial_recieved() 53 | { 54 | return inb(COM1 + 5) & 1; 55 | } 56 | 57 | static uint8_t serial_read() 58 | { 59 | while(!serial_recieved()); 60 | return inb(COM1); 61 | } 62 | 63 | static uint8_t serial_transmit_empty() 64 | { 65 | return inb(COM1 + 5) & 0x20; 66 | } 67 | 68 | static void serial_write(uint8_t chr) 69 | { 70 | if(serial_enabled) 71 | { 72 | #if _DBG_CON_ 73 | serial_tty.fs->write(&serial_tty, 0, 1, &chr); 74 | #else 75 | while(!serial_transmit_empty()); 76 | outb(COM1, chr); 77 | #endif 78 | } 79 | } 80 | 81 | static void serial_str(uint8_t *str) 82 | { 83 | if(serial_enabled) 84 | { 85 | #if _DBG_CON_ 86 | serial_tty.fs->write(&serial_tty, 0, strlen(str), str); 87 | #else 88 | while(*str) serial_write(*str++); 89 | #endif 90 | } 91 | } 92 | 93 | static void serial_end() 94 | { 95 | serial_enabled = 0; 96 | #if _DBG_CON_ 97 | //kfree(serial_tty_dev.virtcon->buf); 98 | //kfree(serial_tty_dev.virtcon); 99 | #endif 100 | } 101 | 102 | serial_t serial = (serial_t){ 103 | .init = &init_com1, 104 | .write = &serial_write, 105 | .write_str = &serial_str, 106 | .end = &serial_end, 107 | }; 108 | -------------------------------------------------------------------------------- /kernel/misc/string.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | uint32_t strlen(uint8_t *str) 6 | { 7 | uint32_t len = 0; 8 | while(*str++) ++len; 9 | return len; 10 | } 11 | 12 | uint8_t *strdup(uint8_t *str) 13 | { 14 | uint8_t *tmp = kmalloc(strlen(str) + 1); 15 | uint8_t *ret = tmp; 16 | while( *str && (*tmp++ = *str++)); 17 | return *tmp = '\0', ret; 18 | } 19 | 20 | uint32_t strcmp(uint8_t *str1, uint8_t *str2) 21 | { 22 | for(; *str1 && *str2 && *str1 == *str2; ++str1, ++str2); 23 | return *str1 - *str2; 24 | } 25 | 26 | void *memcpy(void *dst, void *src, uint64_t size) 27 | { 28 | while(size--) *(uint8_t*)dst++ = *(uint8_t*)src++; 29 | } 30 | 31 | uint8_t *strcat(uint8_t *str1, uint8_t *str2) 32 | { 33 | uint8_t *ret = kmalloc(strlen(str1) + strlen(str2) + 1); 34 | uint8_t *_ret = ret; 35 | uint32_t i = 0; 36 | uint32_t str1_len = strlen(str1); 37 | uint32_t str2_len = strlen(str2); 38 | while(i++ < str1_len) 39 | *ret++ = *str1++; 40 | i = 0; 41 | while(i++ < str2_len) 42 | *ret++ = *str2++; 43 | *ret = '\0'; 44 | return _ret; 45 | } 46 | 47 | void *memset(void *addr, uint8_t val, uint32_t size) 48 | { 49 | uint8_t *_addr = (uint8_t*)addr; 50 | while(size--) *_addr++ = val; 51 | return (void*)addr; 52 | } 53 | 54 | uint8_t *itoa(uint32_t val) 55 | { 56 | uint8_t *buf = kmalloc(12); 57 | buf[11] = '\0'; 58 | uint32_t i = 11; 59 | if(!val) return (buf[10] = '0'), &buf[10]; 60 | while(val) 61 | { 62 | buf[--i] = '0' + val%10; 63 | val /= 10; 64 | } 65 | return (uint8_t*)&buf[i]; 66 | } 67 | 68 | uint8_t *strndup(uint8_t *src, uint32_t len) 69 | { 70 | uint8_t *ret = kmalloc(len + 1); 71 | uint32_t i; 72 | for(i = 0; i < len; ++i) 73 | ret[i] = src[i]; 74 | ret[i] = '\0'; 75 | return ret; 76 | } 77 | 78 | uint32_t isdigit(uint8_t chr) 79 | { 80 | return chr >= '0' && chr <= '9'; 81 | } 82 | 83 | uint32_t isalpha(uint8_t chr) 84 | { 85 | return (chr >= 'a' && chr <= 'z') || (chr >= 'A' && chr <= 'Z'); 86 | } 87 | 88 | uint32_t within(uint8_t chr, uint8_t *str) 89 | { 90 | while(*str) 91 | if(chr == *str++) 92 | return 1; 93 | return 0; 94 | } 95 | -------------------------------------------------------------------------------- /kernel/obj/.bashrc: -------------------------------------------------------------------------------- 1 | export PATH=PATH:/opt/local/bin 2 | -------------------------------------------------------------------------------- /kernel/sys/Makefile: -------------------------------------------------------------------------------- 1 | 2 | include ../Makefile.cfg 3 | 4 | OBJ = process.o syscall.o scheduler.o signal.o 5 | OUT=../obj 6 | 7 | CFLAGS = -c -I ../include/ -mcmodel=large -nostdlib -ffreestanding 8 | 9 | all: $(OBJ) 10 | ${CP} $(OBJ) $(OUT) 11 | 12 | $(OUT)/%.o: %.c 13 | $(CC) $(CFLAGS) $< -o $@ 14 | 15 | clean: 16 | ${RM} -f $(OBJ) 17 | 18 | -------------------------------------------------------------------------------- /kernel/sys/process.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | extern process_t *current_process; 12 | /* 13 | typedef struct 14 | { 15 | uint8_t *buf; 16 | uint64_t entry; 17 | uint32_t text_off; 18 | uint32_t text_size; 19 | uint64_t text_addr; 20 | uint32_t data_off; 21 | uint32_t data_size; 22 | uint64_t data_addr; 23 | uint64_t bss_off; 24 | uint32_t bss_size; 25 | uint64_t bss_addr; 26 | } elf_t; 27 | 28 | elf_t *parse_elf(inode_t *file) 29 | { 30 | uint8_t *buf = kmalloc(file->size); 31 | file->fs->read(file, 0, file->size, buf); 32 | 33 | elf_t *ret = kmalloc(sizeof(elf_t)); 34 | elf_hdr_t *hdr = (elf_hdr_t*)buf; 35 | elf_section_hdr_t *text = (elf_section_hdr_t*)(buf + hdr->shoff + hdr->shentsize); 36 | elf_section_hdr_t *data = (elf_section_hdr_t*)(buf + hdr->shoff + 2 * hdr->shentsize); 37 | 38 | uint32_t c = 2; 39 | elf_section_hdr_t *bss = (elf_section_hdr_t*)(buf + hdr->shoff + 3 * hdr->shentsize); 40 | while(c < hdr->shnum && bss->type != 8) //SHT_NOBITS 41 | { 42 | bss = (elf_section_hdr_t*)(buf + hdr->shoff + c++ * hdr->shentsize); 43 | } 44 | 45 | if(bss->type != 8) bss = NULL; 46 | 47 | *ret = 48 | (elf_t) 49 | { 50 | .buf = buf, 51 | .entry = hdr->entry, 52 | .text_off = text->off, 53 | .text_size = text->size, 54 | .text_addr = text->addr, 55 | .data_off = data->off, 56 | .data_size = data->size, 57 | .data_addr = data->addr, 58 | .bss_off = bss ? bss->off : 0, 59 | .bss_size = bss ? bss->size : 0, 60 | .bss_addr = bss ? bss->addr : data->addr + data->size, 61 | }; 62 | return ret; 63 | } 64 | */ 65 | uint64_t switch_pdpt(uint64_t pdpt) 66 | { 67 | uint64_t ret = *PML4; 68 | *PML4 = pdpt | 7; 69 | TLB_flush(); 70 | return ret; 71 | } 72 | 73 | void map_mem_user(uint64_t pdpt, uint64_t *ptr, uint32_t size) 74 | { 75 | uint64_t cur_pdpt = switch_pdpt(pdpt); 76 | uint64_t endptr = (uint64_t)ptr + size; 77 | debug("endptr %lx ", endptr); 78 | uint32_t psize = endptr - (uint64_t)ptr / 0x1000 * 0x1000; 79 | uint32_t tsize = endptr - (uint64_t)ptr / 0x200000 * 0x200000; 80 | uint32_t dsize = endptr - (uint64_t)ptr / 0x40000000 * 0x40000000; 81 | 82 | uint32_t pages = psize/0x1000 + (psize%0x1000 ?1:0); 83 | uint32_t tbls = tsize/0x200000 + (tsize%0x200000 ?1:0); 84 | uint32_t pds = dsize/0x40000000 + (dsize%0x40000000?1:0); 85 | 86 | debug("ptr %lx Pages %d Tables %d PDs %d\n", ptr, pages, tbls, pds); 87 | uint32_t pindex = ((uint64_t)ptr) / 0x1000; 88 | uint32_t tindex = pindex/0x200; 89 | uint32_t dindex = tindex/0x200; 90 | 91 | //debug("Index [%d]\n", index); 92 | 93 | uint64_t 94 | *init_pd = (uint64_t*)(0x7FFFFFF000 + 0x8 * dindex - 0x8), 95 | *init_tbl = (uint64_t*)(0x7FFFE00000 + 0x8 * tindex - 0x8), 96 | *init_page = (uint64_t*)(0x7FC0000000 + 0x8 * pindex - 0x8); 97 | 98 | //debug("ipd %lx\nitbl %lx\nip %lx\n", init_pd + 1, init_tbl + 1, init_page + 1); 99 | 100 | while(pds--) 101 | if(!(*++init_pd&1)) *init_pd = mman.get_frame() | 7; 102 | while(tbls--) 103 | if(!(*++init_tbl&1)) *init_tbl = mman.get_frame() | 7; 104 | while(pages--) 105 | if(!(*++init_page&1)) *init_page = mman.get_frame() | 7; 106 | switch_pdpt(cur_pdpt); 107 | } 108 | 109 | void unmap_mem_user(uint64_t pdpt, uint64_t *ptr, uint32_t size) 110 | { 111 | uint64_t cur_pdpt = switch_pdpt(pdpt); 112 | //memset(ptr, 0, size); 113 | 114 | uint32_t pages = size/0x1000 + (size%0x1000?1:0); 115 | uint32_t tbls = pages/0x200 + (pages%0x200?1:0); 116 | uint32_t pds = tbls/0x200 + (tbls%0x200?1:0); 117 | 118 | uint32_t pindex = ((uint64_t)ptr) / 0x1000; 119 | uint32_t tindex = pindex/0x200; 120 | uint32_t dindex = tindex/0x200; 121 | 122 | //debug("Index [%d]\n", index); 123 | /* 124 | uint64_t 125 | *init_pd = (uint64_t*)(0x7FFFFFF000 + 0x8 * dindex - 0x8), 126 | *init_tbl = (uint64_t*)(0x7FFFE00000 + 0x8 * tindex - 0x8), 127 | *init_page = (uint64_t*)(0x7FC0000000 + 0x8 * pindex - 0x8); 128 | */ 129 | //debug("ipd %lx\nitbl %lx\nip %lx\n", init_pd + 1, init_tbl + 1, init_page + 1); 130 | 131 | 132 | uint32_t i, j, k; 133 | for(i = 0; i < pds; ++i) 134 | { 135 | uint64_t *pd = (uint64_t*)(0x7FFFFFF000 + 0x8 * dindex + 0x8 * i); 136 | if(*pd&1) 137 | { 138 | for(j = 0; j < MIN(tbls, 0x200); ++j) 139 | { 140 | uint64_t *tbl = (uint64_t*)(0x7FFFE00000 + 0x8 * tindex + 0x8 * j); 141 | if(*tbl&1) 142 | { 143 | for(k = 0; k < MIN(pages, 0x200); ++k) 144 | { 145 | uint64_t *page = (uint64_t*)(0x7FC0000000 + 0x8 * pindex + 0x8 * k); 146 | if(*page&1) 147 | { 148 | mman.set(*page); 149 | *page = 0; 150 | } 151 | } 152 | pages -= MIN(pages, 0x200); 153 | mman.set(*tbl); 154 | *tbl = 0; 155 | } 156 | } 157 | tbls -= MIN(tbls, 0x200); 158 | mman.set(*pd); 159 | *pd = 0; 160 | } 161 | } 162 | switch_pdpt(cur_pdpt); 163 | } 164 | 165 | void copy_mem_user(uint64_t pdpt, void *dst, void *src, uint32_t size) 166 | { 167 | uint64_t cur_pdpt = switch_pdpt(pdpt); 168 | } 169 | 170 | void exit_process(process_t *p) 171 | { 172 | debug("Exitinig process %s\n", p->name); 173 | 174 | unmap_mem_user(p->pdpt, (uint64_t*)p->addr, p->size * 0x1000); 175 | unmap_mem_user(p->pdpt, 176 | (uint64_t*)(USER_STACK - USER_STACK_SIZE), USER_STACK_SIZE); 177 | 178 | //for(;;); 179 | 180 | if(p->parent) 181 | signal_send(p->parent, SIGCHLD); 182 | 183 | mman.set(p->pdpt); 184 | extern void deschedule_process(process_t*); 185 | deschedule_process(p); 186 | kfree(p->name); 187 | kfree(p); 188 | //switch_pdpt(cur_pdpt); 189 | TLB_flush(); 190 | } 191 | 192 | uint64_t get_pdpt() 193 | { 194 | //debug("PML4 %lx\n", PML4); 195 | uint64_t _pdpt = *PML4; 196 | //debug("_PDPT %lx\n", _pdpt); 197 | uint64_t pdpt = mman.get_frame(); 198 | extern uint64_t kernel_end; 199 | *PML4 = ((uint64_t)kernel_end) | 3; 200 | *(uint64_t*)(0x8) = pdpt | 3; 201 | memset((void*)0x1000, 0, 0x1000 - 0x8); 202 | *(uint64_t*)(0x1FF8) = pdpt | 3; 203 | *PML4 = _pdpt; 204 | TLB_flush(); 205 | return pdpt; 206 | } 207 | 208 | uint64_t get_pid() 209 | { 210 | static uint64_t pid = 0; 211 | return ++pid; 212 | } 213 | 214 | #define SHT_PROGBITS 0x1 215 | #define SHF_ALLOC 0x2 216 | 217 | process_t *load_elf(char *filename) 218 | { 219 | inode_t *file = vfs_trace_path(vfs_root, filename); 220 | if(!file) return NULL; 221 | 222 | uint8_t *buf = kmalloc(file->size); 223 | file->fs->read(file, 0, file->size, buf); 224 | 225 | elf_hdr_t *hdr = (elf_hdr_t*)buf; 226 | elf_section_hdr_t *ehdr = (elf_section_hdr_t*)(buf + hdr->shoff); 227 | 228 | uint32_t j; 229 | uint64_t addr = -1, size = 0; 230 | for(j = 0; j < hdr->shnum; ++j) 231 | { 232 | ehdr = (elf_section_hdr_t*)(buf + hdr->shoff + j * hdr->shentsize); 233 | if(ehdr->flags & SHF_ALLOC) 234 | { 235 | addr = MIN(addr, ehdr->addr); 236 | size = MAX(size, ehdr->addr + ehdr->size); 237 | } 238 | } 239 | 240 | 241 | process_t *proc = kmalloc(sizeof(process_t)); 242 | proc->pdpt = get_pdpt(); 243 | proc->name = strdup(filename); 244 | proc->pid = get_pid(); 245 | 246 | proc->addr = addr; 247 | proc->size = size/0x1000 + (size%0x1000?1:0); 248 | proc->heap = proc->size * 0x1000; 249 | 250 | proc->fds.len = 0; 251 | proc->fds.max_len = 5; 252 | proc->fds.ent = kmalloc(5 * sizeof(process_file_t)); 253 | 254 | map_mem_user(proc->pdpt, (uint64_t*)addr, proc->size * 0x1000); // Heap 255 | map_mem_user(proc->pdpt, 256 | (uint64_t*)(USER_STACK - USER_STACK_SIZE), USER_STACK_SIZE); // Stack 257 | 258 | uint64_t cur_pdpt = switch_pdpt(proc->pdpt); 259 | 260 | // let's load the file at 0x0 261 | 262 | ehdr = (elf_section_hdr_t*)(buf + hdr->shoff); 263 | for(j = 0; j < hdr->shnum; ++j) 264 | { 265 | ehdr = (elf_section_hdr_t*)(buf + hdr->shoff + j * hdr->shentsize); 266 | if(ehdr->type == SHT_PROGBITS && ehdr->flags & SHF_ALLOC) 267 | { 268 | //debug("memcpy(0x%lx, 0x%lx, 0x%x)\n", ehdr->addr, buf + ehdr->off, ehdr->size); 269 | memcpy(ehdr->addr, buf + ehdr->off, ehdr->size); 270 | } 271 | } 272 | 273 | kfree(buf); 274 | 275 | proc->stat.rip = hdr->entry; 276 | proc->stat.rsp = USER_STACK; 277 | 278 | switch_pdpt(cur_pdpt); 279 | return proc; 280 | } 281 | 282 | void switch_process(process_t *p) 283 | { 284 | if(current_process->fstat) 285 | save_fpu(); 286 | 287 | if(!p->fstat) 288 | disable_fpu(); 289 | 290 | debug("Switching process\n"); 291 | debug("RIP %lx\n", p->stat.rip); 292 | switch_pdpt(p->pdpt); 293 | if(p->sigqueue) // Any pending signals !? 294 | { 295 | void *stack = (void*)p->stat.rsp; 296 | stack -= sizeof(stat_t); 297 | memcpy(stack, &p->stat, sizeof(stat_t)); 298 | stack -= sizeof(uint64_t); 299 | *(uint64_t*)stack = -1; 300 | p->stat.rsp = (uint64_t)stack; 301 | signal_queue_t *q = p->sigqueue; 302 | p->stat.rip = (uint64_t)p->handlers[q->signum].sa_handler; 303 | p->sigqueue = q->next; 304 | kfree(q); 305 | } 306 | switch_context(&p->stat); 307 | } 308 | 309 | void copy_process_stat(process_t *dest, process_t *src) 310 | { 311 | memcpy(&dest->stat, &src->stat, sizeof(stat_t)); 312 | } 313 | 314 | uint32_t forking = 0; 315 | void fork_process(process_t *p) 316 | { 317 | forking = 1; 318 | debug("Forking procss [%s]\n", p->name); 319 | process_t *new_process = kmalloc(sizeof(process_t)); 320 | memcpy(new_process, p, sizeof(process_t)); 321 | new_process->name = strcat(p->name, " (fork)"); 322 | new_process->parent = p; 323 | new_process->pdpt = get_pdpt(); 324 | 325 | //new_process->size = p->size; 326 | new_process->pid = get_pid(); 327 | //new_process->fds = p->fds; 328 | new_process->fds.ent = kmalloc(new_process->fds.max_len * sizeof(process_file_t*)); 329 | memcpy(new_process->fds.ent, p->fds.ent, p->fds.max_len * sizeof(process_file_t*)); 330 | new_process->status = READY; 331 | 332 | map_mem_user(new_process->pdpt, (uint64_t*)new_process->addr, p->size * 0x1000); // Heap 333 | map_mem_user(new_process->pdpt, 334 | (uint64_t*)(USER_STACK - USER_STACK_SIZE), USER_STACK_SIZE); // Stack 335 | 336 | uint8_t *buf = kmalloc( (p->size + 1) * 0x1000 ); 337 | uint8_t *stack = kmalloc( USER_STACK_SIZE + 0x1000 ); 338 | 339 | static uint64_t i = 0; 340 | 341 | i = new_process->addr/0x1000*0x1000; 342 | // Copying heap 343 | asm volatile ("movq %0, %%r10;"::"g"(&&fork_copy_start)); 344 | fork_copy_start: 345 | while(i < p->size * 0x1000) 346 | { 347 | if(fork_skip_page) 348 | { 349 | i += 0x1000; 350 | fork_skip_page = 0; 351 | } 352 | if(i >= p->size * 0x1000) break; 353 | 354 | //memcpy(buf + i, i, 0x1000); 355 | uint32_t j; 356 | for(j = 0; j < 0x1000; ++j) 357 | *(buf+i+j) = *(uint8_t*)(i+j); 358 | i += 0x1000; 359 | } 360 | 361 | // Copying stack 362 | for(i = 0; i < USER_STACK_SIZE; ++i) 363 | *(stack+i) = *(uint8_t*)(USER_STACK - USER_STACK_SIZE + i); 364 | 365 | switch_pdpt(new_process->pdpt); 366 | 367 | // Restoring heap 368 | for(i = new_process->addr; i < p->size * 0x1000; ++i) 369 | *(uint8_t*)i = *(buf+i); 370 | 371 | // Restoring stack 372 | for(i = 0; i < USER_STACK_SIZE; ++i) 373 | *(uint8_t*)(USER_STACK - USER_STACK_SIZE + i) = *(stack+i); 374 | 375 | kfree(buf); 376 | kfree(stack); 377 | 378 | // Copying process state 379 | copy_process_stat(new_process, p); 380 | 381 | current_process->stat.rax = new_process->pid; 382 | new_process->stat.rax = 0; 383 | 384 | schedule_process(new_process); 385 | forking = 0; 386 | kernel_idle(); 387 | } 388 | 389 | void exec_process(uint8_t *path, uint8_t **arg, uint8_t **env) 390 | { 391 | inode_t *file = vfs_trace_path(vfs_root, path); 392 | if(!file) return; 393 | 394 | // Copying arguments 395 | uint32_t arglen = 0, argc; 396 | if(arg) 397 | for(argc = 0; arg[argc]; ++argc) 398 | { 399 | //debug("arg[%d]: %s\n", argc, arg[argc]); 400 | arglen += strlen(arg[argc]) + 1; 401 | } 402 | 403 | int namelen = strlen(path) + 1; 404 | char *args = kmalloc(namelen + arglen + 1); 405 | memcpy(args, path, namelen); 406 | if(arglen) memcpy(args + namelen, *arg, arglen); 407 | *(args + namelen + arglen) = '\0'; 408 | 409 | current_process->args = args; 410 | current_process->argslen = arglen + namelen + 1; 411 | 412 | // Copying environemt 413 | char *envs; 414 | arglen = 0; 415 | if(env) 416 | { 417 | for(argc = 0; env[argc]; ++argc) 418 | arglen += strlen(env[argc]) + 1; 419 | 420 | envs = kmalloc(arglen + 1); 421 | memcpy(envs, *env, arglen); 422 | *(envs + arglen) = '\0'; 423 | } else 424 | { 425 | arglen = 1; 426 | envs = "\0\0"; 427 | } 428 | 429 | current_process->envs = envs; 430 | current_process->envslen = arglen + 1; 431 | 432 | kfree(current_process->name); 433 | current_process->name = strdup(path); 434 | 435 | uint8_t *buf = kmalloc(file->size); 436 | file->fs->read(file, 0, file->size, buf); 437 | 438 | elf_hdr_t *hdr = (elf_hdr_t*)buf; 439 | elf_section_hdr_t *ehdr = (elf_section_hdr_t*)(buf + hdr->shoff); 440 | 441 | uint64_t addr = -1, size = 0; 442 | uint32_t j; 443 | for(j = 0; j < hdr->shnum; ++j) 444 | { 445 | ehdr = (elf_section_hdr_t*)(buf + hdr->shoff + j * hdr->shentsize); 446 | if(ehdr->flags & SHF_ALLOC) 447 | { 448 | addr = MIN(addr, ehdr->addr); 449 | size = MAX(size, ehdr->addr + ehdr->size); 450 | } 451 | } 452 | 453 | current_process->addr = addr; 454 | current_process->size = size/0x1000 + (size%0x1000?1:0); 455 | current_process->heap = current_process->size * 0x1000; 456 | 457 | // TODO : unmap extra allocated virtual address space 458 | map_mem_user(current_process->pdpt, (uint64_t*)addr, current_process->size * 0x1000 ); 459 | map_mem_user(current_process->pdpt, 460 | (uint64_t*)(USER_STACK - USER_STACK_SIZE), USER_STACK_SIZE); // Stack 461 | 462 | uint64_t cur_pdpt = switch_pdpt(current_process->pdpt); 463 | 464 | // let's load the file 465 | 466 | ehdr = (elf_section_hdr_t*)(buf + hdr->shoff); 467 | for(j = 0; j < hdr->shnum; ++j) 468 | { 469 | ehdr = (elf_section_hdr_t*)(buf + hdr->shoff + j * hdr->shentsize); 470 | if(ehdr->type == SHT_PROGBITS && ehdr->flags & SHF_ALLOC) 471 | { 472 | memcpy(ehdr->addr, buf + ehdr->off, ehdr->size); 473 | } 474 | } 475 | 476 | kfree(buf); 477 | 478 | //Reset signals 479 | memset(¤t_process->handlers, 0, sizeof(current_process->handlers)); 480 | 481 | current_process->stat.rip = hdr->entry; 482 | current_process->stat.rsp = USER_STACK; 483 | 484 | switch_pdpt(cur_pdpt); 485 | kernel_idle(); 486 | } 487 | 488 | uint32_t get_fd(process_t *proc) 489 | { 490 | uint32_t i; 491 | for(i = 0; i < proc->fds.len; ++i) 492 | { 493 | if(!proc->fds.ent[i].inode) return i; 494 | } 495 | return proc->fds.len++; 496 | } 497 | 498 | uint32_t validate(process_t *proc, void *ptr) 499 | { 500 | if( (uint64_t)ptr <= proc->heap * 0x1000 || 501 | ((uint64_t)ptr <= USER_STACK && (uint64_t)ptr >= (USER_STACK - USER_STACK_SIZE))) 502 | return 1; 503 | return 0; 504 | } 505 | -------------------------------------------------------------------------------- /kernel/sys/scheduler.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | typedef struct 10 | { 11 | uint32_t count; 12 | process_t *head; 13 | process_t *tail; 14 | } process_queue_t; 15 | 16 | process_queue_t process_queue; 17 | process_t *current_process; 18 | 19 | void dump_processes() 20 | { 21 | debug("\n"); 22 | process_t *p = process_queue.head; 23 | while(p) 24 | { 25 | debug("#%lx [%s]\n", p, p->name); 26 | p = p->next; 27 | } 28 | debug("\n"); 29 | } 30 | 31 | void spawn_init(process_t *init) 32 | { 33 | init->status = READY; 34 | init->prev = NULL; 35 | init->next = NULL; 36 | process_queue.head = init; 37 | process_queue.tail = init; 38 | process_queue.count = 1; 39 | current_process = init; 40 | 41 | init->fstat = NULL; 42 | //schedule_process(init); 43 | switch_process(init); 44 | //kernel_idle(); 45 | } 46 | 47 | uint8_t kidle = 0; 48 | 49 | void schedule(regs_t *regs) 50 | { 51 | extern void irq_ack(uint32_t); 52 | irq_ack(0); 53 | static uint32_t x = 0; 54 | //if(x++%32) return; 55 | 56 | debug("Scheduling\n"); 57 | dump_processes(); 58 | if(!kidle) 59 | { 60 | memcpy(¤t_process->stat, regs, sizeof(regs_t)); 61 | /* 62 | current_process->stat.rax = regs->rax; 63 | current_process->stat.rdx = regs->rdx; 64 | current_process->stat.rcx = regs->rcx; 65 | current_process->stat.rbx = regs->rbx; 66 | current_process->stat.rsp = regs->rsp; 67 | current_process->stat.rbp = regs->rbp; 68 | current_process->stat.rsi = regs->rsi; 69 | current_process->stat.rdi = regs->rdi; 70 | current_process->stat.r8 = regs->r8; 71 | current_process->stat.r9 = regs->r9; 72 | current_process->stat.r10 = regs->r10; 73 | current_process->stat.r11 = regs->r11; 74 | current_process->stat.r12 = regs->r12; 75 | current_process->stat.r13 = regs->r13; 76 | current_process->stat.r14 = regs->r14; 77 | current_process->stat.r15 = regs->r15; 78 | current_process->stat.rip = regs->rip; 79 | current_process->stat.rflags = regs->rflags; 80 | */ 81 | } else kidle = 0; 82 | 83 | process_t *p = current_process?current_process->next:NULL; 84 | if(p) 85 | { 86 | while(p && p->status != READY) 87 | { 88 | if(p->wait_us) 89 | { 90 | if(p->wait_us <= ((ticks - p->ticks) * pit_freq + (sub_ticks - p->sub_ticks)) * sub_tick_us) 91 | { 92 | p->status = READY; 93 | p->wait_us = 0; 94 | p->stat.rax = 0; 95 | break; 96 | } 97 | } 98 | p = p->next; 99 | } 100 | // Now we either got a ready process or the last process 101 | if(p && p->status == READY) 102 | { 103 | debug("Found next %lx [%s]\n", p, p->name); 104 | switch_process(current_process = p); 105 | } 106 | } 107 | 108 | // Otherwise we should just loop 109 | if(process_queue.head) 110 | { 111 | p = process_queue.head; 112 | while(p && p->status != READY) 113 | { 114 | if(p->wait_us) 115 | { 116 | if(p->wait_us <= ((ticks - p->ticks) * pit_freq + (sub_ticks - p->sub_ticks)) * sub_tick_us) 117 | { 118 | p->status = READY; 119 | p->wait_us = 0; 120 | p->stat.rax = 0; 121 | break; 122 | } 123 | } 124 | p = p->next; 125 | } 126 | 127 | // Now we either got a ready process or the last process 128 | if(p && p->status == READY) 129 | { 130 | debug("Loop %lx [%s]\n", p, p->name); 131 | switch_process(current_process = p); 132 | } 133 | } 134 | 135 | // Otherwise we got nothing so we should just idle 136 | kernel_idle(); 137 | } 138 | 139 | process_t *process_by_pid(pid_t pid) 140 | { 141 | process_t *p = process_queue.head; 142 | while(p && p->pid != pid) p = p->next; 143 | return p; 144 | } 145 | 146 | void schedule_process(process_t *p) 147 | { 148 | debug("Added [%s] to queue\n", p->name); 149 | p->next = NULL; 150 | p->prev = process_queue.tail; 151 | process_queue.count++; 152 | process_queue.tail->next = p; 153 | process_queue.tail = p; 154 | } 155 | 156 | 157 | void deschedule_process(process_t *p) 158 | { 159 | if(p->prev) 160 | { 161 | if(p->next) 162 | p->prev->next = p->next; 163 | else if(process_queue.tail == p) 164 | { 165 | p->prev->next = NULL; 166 | process_queue.tail = p->prev; 167 | } 168 | } 169 | else if (process_queue.head == p) 170 | { 171 | process_queue.head = p->next; 172 | p->next->prev = NULL; 173 | } 174 | else 175 | { 176 | // Where the hell did you get this process from !!? 177 | } 178 | } 179 | -------------------------------------------------------------------------------- /kernel/sys/signal.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | int signal_default_action[] = 10 | { 11 | IGN, //0 12 | TRM, //SIGHUP 13 | TRM, //SIGINT 14 | TRM, //SIGQUIT 15 | TRM, //SIGILL 16 | TRM, //SIGTRAP 17 | TRM, //SIGABRT 18 | TRM, //SIGBUS 19 | TRM, //SIGFPE 20 | TRM, //SIGKILL 21 | IGN, //SIGUSR1 22 | TRM, //SIGSEGV 23 | IGN, //SIGUSR2 24 | TRM, //SIGPIPE 25 | TRM, //SIGALRM 26 | IGN, //__UNUSED__ 27 | CNT, //SIGCHLD IGN XXX 28 | CNT, //SIGCONT 29 | STP, //SIGSTOP 30 | STP, //SIGTSTP 31 | STP, //SIGTTIN 32 | STP, //SIGTTOU 33 | }; 34 | 35 | char *signal_names[] = 36 | { 37 | "SIGHUP", 38 | "SIGINT", 39 | "SIGQUIT", 40 | "SIGILL", 41 | "SIGTRAP", 42 | "SIGABRT", 43 | "SIGBUS", 44 | "SIGFPE", 45 | "SIGKILL", 46 | "SIGUSR1", 47 | "SIGSEGV", 48 | "SIGUSR2", 49 | "SIGPIPE", 50 | "SIGALRM", 51 | "__UNUSED__", 52 | "SIGCHLD", 53 | "SIGCONT", 54 | "SIGSTOP", 55 | "SIGTSTP", 56 | "SIGTTIN", 57 | "SIGTTOU", 58 | }; 59 | 60 | void signal_send(process_t *p, signal_num_t signal) 61 | { 62 | inode_t *p_stdout = p->fds.len > 2 ? p->fds.ent[1].inode : NULL; 63 | 64 | uint8_t *msg; 65 | 66 | if(p->handlers[signal].sa_handler) 67 | { 68 | if((uint64_t)p->handlers[signal].sa_handler == 1) // Ignore 69 | { 70 | debug("Ignoring signal\n"); 71 | return; 72 | } 73 | else if((uint64_t)p->handlers[signal].sa_handler == -1) // Error ( terminate ) 74 | { 75 | if(p_stdout) 76 | { 77 | msg = strcat(strcat("Process terminated [", signal_names[signal - 1]), "]\n"); 78 | vfs_write(p_stdout, 0, strlen(msg), msg); 79 | } 80 | exit_process(p); 81 | return; 82 | } 83 | debug("Queuing signal\n"); 84 | if(!p->sigqueue) 85 | { 86 | signal_queue_t *q = p->sigqueue = kmalloc(sizeof(signal_queue_t)); 87 | q->signum = signal; 88 | q->next = NULL; 89 | } 90 | else 91 | { 92 | signal_queue_t *q = p->sigqueue; 93 | while(q->next) q = q->next; 94 | q->next = kmalloc(sizeof(signal_queue_t)); 95 | q = q->next; 96 | q->signum = signal; 97 | } 98 | } 99 | 100 | else 101 | { 102 | int action = signal_default_action[signal]; 103 | switch(action) 104 | { 105 | case IGN: break; 106 | case TRM: 107 | if(p_stdout) 108 | { 109 | msg = strcat(strcat("Process terminated [", signal_names[signal - 1]), "]\n"); 110 | vfs_write(p_stdout, 0, strlen(msg), msg); 111 | } 112 | exit_process(p); 113 | break; 114 | case STP: 115 | p->status = WAITING; 116 | break; 117 | case CNT: 118 | p->status = READY; 119 | break; 120 | } 121 | } 122 | } 123 | 124 | void signal_send_by_pid(pid_t pid, signal_num_t signal) 125 | { 126 | process_t *p = process_by_pid(pid); 127 | if(!p) return; 128 | signal_send(p, signal); 129 | } 130 | -------------------------------------------------------------------------------- /kernel/sys/syscall.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | void kernel_idle() 13 | { 14 | // FIXME : This should minimize I/O wait time but for processes invoking 15 | // many consequent syscalls this will keep other processes starving 16 | if(current_process && current_process->status == READY) 17 | switch_process(current_process); 18 | 19 | extern uint8_t kidle; 20 | kidle = 1; 21 | for(;;) 22 | { 23 | schedule(); 24 | asm("sti; hlt; cli;"); 25 | } 26 | } 27 | 28 | 29 | #define RETURN(val) \ 30 | { \ 31 | current_process->stat.rax = val; \ 32 | kernel_idle(); \ 33 | } \ 34 | 35 | SYS(sys_exit) // 0 36 | { 37 | debug("Exiting\n"); 38 | exit_process(current_process); 39 | //kernel_idle(); // We should not idle here 40 | extern uint8_t kidle; 41 | kidle = 1; 42 | schedule(); 43 | } 44 | 45 | SYS(sys_open) // rbx path, rcx flags 46 | { 47 | if(!validate(current_process, (void*)rbx)) RETURN(-1); 48 | 49 | uint32_t fd = get_fd(current_process); 50 | debug("Openning file %s [%s:%d]\n", rbx, current_process->name, fd); 51 | inode_t *i = vfs_trace_path(vfs_root, (uint8_t*)rbx); 52 | if(i) 53 | { 54 | if(i->type == FS_MOUNTPOINT) 55 | { 56 | debug("Openning mount point\n"); 57 | i = ((vfs_mountpoint_t*)i->p)->inode; 58 | } 59 | 60 | current_process->fds.ent[fd].inode = i; 61 | current_process->fds.ent[fd].offset = 0; 62 | current_process->stat.rax = fd; 63 | } 64 | else 65 | current_process->stat.rax = -1; 66 | 67 | kernel_idle(); 68 | } 69 | 70 | SYS(sys_read) // rbx fd, rcx buf, rdx len 71 | { 72 | if( rbx > current_process->fds.len || 73 | !current_process->fds.ent[rbx].inode || 74 | !validate(current_process, (void*)rcx)) RETURN(-1); 75 | 76 | debug("Reading fd:%d #%lx, [%d]\n", rbx, rcx, rdx); 77 | inode_t *inode = current_process->fds.ent[rbx].inode; 78 | debug("inode %lx\n", inode); 79 | uint32_t offset = current_process->fds.ent[rbx].offset; 80 | uint32_t size = vfs_read(inode, offset, rdx, (void*)rcx); 81 | current_process->fds.ent[rbx].offset += size; 82 | RETURN(size); 83 | } 84 | 85 | SYS(sys_write) // rbx fd, rcx buf, rdx len 86 | { 87 | if( rbx > current_process->fds.len || 88 | !current_process->fds.ent[rbx].inode || 89 | !validate(current_process, (void*)rcx)) 90 | { 91 | current_process->stat.rax = -1; 92 | kernel_idle(); 93 | } 94 | 95 | inode_t *inode = current_process->fds.ent[rbx].inode; 96 | uint64_t offset = current_process->fds.ent[rbx].offset; 97 | debug("Wrtiting to inode %lx\n", inode); 98 | 99 | int len = vfs_write(inode, offset, rdx, (void*)rcx); 100 | RETURN(len); 101 | } 102 | 103 | SYS(sys_lseek) // rbx fd, rcx offset, rdx whence 104 | { 105 | if( rbx > current_process->fds.len || 106 | !current_process->fds.ent[rbx].inode) RETURN(-1); 107 | 108 | switch(rdx) 109 | { 110 | case 0: //SEEK_SET 111 | current_process->fds.ent[rbx].offset = rcx; 112 | break; 113 | case 1: //SEEK_CUR 114 | current_process->fds.ent[rbx].offset += rcx; 115 | break; 116 | case 2: //SEEK_END 117 | current_process->fds.ent[rbx].offset = current_process->fds.ent[rbx].inode->size; 118 | break; 119 | default: 120 | current_process->stat.rax = -1; 121 | kernel_idle(); 122 | } 123 | RETURN(current_process->fds.ent[rbx].offset); 124 | } 125 | 126 | SYS(sys_close) // rbx fd 127 | { 128 | if(rbx > current_process->fds.len) 129 | { 130 | current_process->stat.rax = -1; 131 | kernel_idle(); 132 | } 133 | 134 | current_process->fds.ent[rbx].inode = NULL; 135 | current_process->fds.ent[rbx].offset = 0; 136 | RETURN(0); 137 | } 138 | 139 | SYS(sys_fork) 140 | { 141 | fork_process(current_process); 142 | } 143 | 144 | SYS(sys_execve) // rbx path, rcx argv, rdx env 145 | { 146 | if(rbx) 147 | { 148 | uint8_t *p = strdup((uint8_t*)rbx); 149 | debug("execve(%s, %lx, %lx)\n", p, rcx, rdx); 150 | exec_process(p, (uint8_t**)rcx, (uint8_t**)rdx); 151 | } 152 | RETURN(-1); 153 | } 154 | 155 | SYS(sys_sbrk) // rbx size 156 | { 157 | debug("Allocating %d B for process %s\n", rbx, current_process->name); 158 | if(!rbx) RETURN(current_process->heap); 159 | 160 | //if(current_process->name[0] == 'm') for(;;); 161 | uint64_t ret = current_process->heap; 162 | 163 | if(current_process->size * 0x1000 - current_process->heap > rbx) 164 | { 165 | current_process->heap += rbx; 166 | RETURN(ret); 167 | } 168 | 169 | uint32_t req_size = rbx - (current_process->size * 0x1000 - current_process->heap); 170 | uint32_t req_size_pages = req_size/0x1000 + (req_size%0x1000?1:0); 171 | 172 | #if _LAZYALLOC_ 173 | map_mem_user(current_process->pdpt, 174 | (uint64_t*)(current_process->size * 0x1000), req_size_pages * 0x1000); 175 | #endif 176 | 177 | current_process->size += req_size_pages; 178 | current_process->heap += req_size; 179 | RETURN(ret); 180 | } 181 | 182 | SYS(sys_getpid) 183 | { 184 | RETURN(current_process->pid); 185 | } 186 | 187 | SYS(sys_wait) // rbx status 188 | { 189 | debug("Waiting for childern @%s\n", current_process->name); 190 | current_process->status = WAITING; 191 | //deschedule_process(current_process->pid); 192 | kernel_idle(); 193 | } 194 | 195 | SYS(sys_kill) 196 | { 197 | debug("Signal\n"); 198 | signal_send_by_pid((pid_t)rbx, (signal_num_t)rcx); 199 | RETURN(0); //TODO Actuall checking for signal success 200 | } 201 | 202 | SYS(sys_signal) // rbx signum, rcx signal pointer 203 | { 204 | if(!validate(current_process, (void*)rcx)) 205 | { 206 | current_process->stat.rax = -1; 207 | kernel_idle(); 208 | } 209 | 210 | debug("Registering signal handler %d->%lx\n", rbx, rcx); 211 | void *old_handler = ¤t_process->handlers[(signal_num_t)rbx]; 212 | current_process->handlers[(signal_num_t)rbx].sa_handler = (void*)rcx; 213 | RETURN((uint64_t)old_handler); 214 | } 215 | 216 | SYS(sys_usleep) // rbx time in us 217 | { 218 | debug("uSleep [%d us] on process %s\n", rbx, current_process->name); 219 | current_process->wait_us = rbx; 220 | current_process->ticks = ticks; 221 | current_process->sub_ticks = sub_ticks; 222 | current_process->status = WAITING; 223 | kernel_idle(); 224 | } 225 | 226 | SYS(sys_getatt) // rbx attribute, rcx buf 227 | { 228 | switch(rbx) 229 | { 230 | case 0: // get args length 231 | current_process->stat.rax = current_process->argslen; 232 | break; 233 | case 1: // get args into buffer 234 | if(!validate(current_process, (void*)rcx)) 235 | { 236 | current_process->stat.rax = -1; 237 | kernel_idle(); 238 | } 239 | memcpy((void*)rcx, current_process->args, current_process->argslen); 240 | kernel_idle(); 241 | break; 242 | case 2: // get envs length 243 | current_process->stat.rax = current_process->envslen; 244 | break; 245 | case 3: // get envs into buffer 246 | if(!validate(current_process, (void*)rcx)) 247 | { 248 | current_process->stat.rax = -1; 249 | kernel_idle(); 250 | } 251 | memcpy((void*)rcx, current_process->envs, current_process->envslen); 252 | kernel_idle(); 253 | break; 254 | default: 255 | current_process->stat.rax = -1; 256 | } 257 | kernel_idle(); 258 | } 259 | 260 | SYS(sys_readdir) // rbx fd, rcx index, rdx dirent 261 | { 262 | if( rbx > current_process->fds.len || 263 | !current_process->fds.ent[rbx].inode || 264 | !validate(current_process, (void*)rdx) 265 | ); 266 | 267 | inode_t *inode = current_process->fds.ent[rbx].inode; 268 | 269 | dentry_t *dentry = inode->list; 270 | if(!dentry) { current_process->stat.rax = -1; kernel_idle(); } 271 | 272 | uint32_t index = rcx; 273 | if(index >= dentry->count) { current_process->stat.rax = -1; kernel_idle(); } 274 | 275 | inode_t *i = dentry->head; 276 | while(i && i->next && index--) i = i->next; 277 | 278 | if(i->name) 279 | { 280 | struct dirent *dir = (struct dirent *)rdx; 281 | memcpy(dir->d_name, i->name, strlen(i->name) + 1); 282 | current_process->stat.rax = 0; 283 | } else 284 | current_process->stat.rax = -1; 285 | kernel_idle(); 286 | } 287 | 288 | SYS(sys_getcwd) // rbx buf, rcx size 289 | { 290 | if(!validate(current_process, (void*)rbx) || rcx < strlen(current_process->cwd)) 291 | { 292 | current_process->stat.rax = 0; // NULL 293 | kernel_idle(); 294 | } 295 | 296 | memcpy(rbx, current_process->cwd, strlen(current_process->cwd)); 297 | RETURN(rbx); 298 | } 299 | 300 | SYS(sys_chdir) //rbx path 301 | { 302 | if(!validate(current_process, (void*)rbx) || !vfs_trace_path(vfs_root, (uint8_t*)rbx)) 303 | RETURN(-1); 304 | 305 | if(current_process->cwd) kfree(current_process->cwd); 306 | if(((uint8_t*)rbx)[strlen((uint8_t*)rbx)-1] == '/') 307 | { 308 | current_process->cwd = (uint8_t*)kmalloc(strlen((uint8_t*)rbx)); 309 | memcpy(current_process->cwd, rbx, strlen((uint8_t*)rbx) + 1); 310 | } else 311 | { 312 | uint32_t len = strlen((uint8_t*)rbx); 313 | current_process->cwd = (uint8_t*)kmalloc(len + 2); 314 | memcpy(current_process->cwd, rbx, len + 1); 315 | current_process->cwd[len] = '/'; 316 | current_process->cwd[len + 1] = '\0'; 317 | } 318 | RETURN(0); 319 | } 320 | 321 | SYS(sys_mount) // rbx filesystem, rcx dst, rdx src 322 | { 323 | if( !validate(current_process, (void*)rbx) || 324 | !validate(current_process, (void*)rcx) || 325 | !vfs_trace_path(vfs_root, (uint8_t*)rcx)|| 326 | !(rdx ? validate(current_process, (void*)rdx) : 1) 327 | ) RETURN(-1); 328 | 329 | fs_t *fs = fsman.getfs((uint8_t*)rbx); 330 | if(!fs) RETURN(-2); 331 | 332 | inode_t *src = rdx ? vfs_trace_path(vfs_root, (uint8_t*)rdx) : NULL; 333 | inode_t *dst = vfs_trace_path(vfs_root, (uint8_t*)rcx); 334 | if(!dst) RETURN(-3); 335 | 336 | RETURN(fs->mount(dst, src)); 337 | } 338 | 339 | void *sys_calls[] = 340 | { 341 | sys_exit, 342 | sys_open, 343 | sys_read, 344 | sys_write, 345 | sys_close, 346 | sys_fork, 347 | sys_execve, 348 | sys_sbrk, 349 | sys_getpid, 350 | sys_wait, 351 | sys_kill, 352 | sys_signal, 353 | sys_usleep, 354 | sys_getatt, 355 | sys_lseek, 356 | sys_readdir, 357 | sys_getcwd, 358 | sys_chdir, 359 | sys_mount, 360 | }; 361 | 362 | -------------------------------------------------------------------------------- /libc/Makefile: -------------------------------------------------------------------------------- 1 | include ../kernel/Makefile.cfg 2 | 3 | SRC = src 4 | OBJ = system.o stdio.o stdlib.o unistd.o fcntl.o signal.o 5 | 6 | libc.a: $(OBJ) 7 | ${AR} rcs libc.a obj/*.o 8 | 9 | %.o : $(SRC)/%.c 10 | ${CC} -mcmodel=large -c -fno-builtin -ffreestanding -I include/ $< 11 | @mkdir -p obj/ 12 | @mv $@ obj/ 13 | 14 | clean: 15 | ${RM} -f obj/*.o 16 | @rm -f libc.a 17 | -------------------------------------------------------------------------------- /libc/include/fcntl.h: -------------------------------------------------------------------------------- 1 | #ifndef _FCNTL_H 2 | #define _FCNTL_H 3 | 4 | uint64_t open(const char *path, uint64_t flags); 5 | 6 | #endif 7 | -------------------------------------------------------------------------------- /libc/include/signal.h: -------------------------------------------------------------------------------- 1 | #ifndef _SIGNAL_H 2 | #define _SIGNAL_H 3 | 4 | typedef void(*sighandler_t)(int); 5 | typedef enum 6 | { 7 | SIGHUP = 1, 8 | SIGINT = 2, 9 | SIGQUIT = 3, 10 | SIGILL = 4, 11 | SIGTRAP = 5, 12 | SIGABRT = 6, 13 | SIGBUS = 7, 14 | SIGFPE = 8, 15 | SIGKILL = 9, 16 | SIGUSR1 = 10, 17 | SIGSEGV = 11, 18 | SIGUSR2 = 12, 19 | SIGPIPE = 13, 20 | SIGALRM = 14, 21 | __UNUSED__, 22 | SIGCHLD = 16, 23 | SIGCONT = 17, 24 | SIGSTOP = 18, 25 | SIGTSTP = 19, 26 | SIGTTIN = 20, 27 | SIGTTOU = 21, 28 | } signal_num_t; 29 | 30 | sighandler_t *signal(int signum, sighandler_t handler); 31 | int kill(int pid, int signum); 32 | int raise(int signum); 33 | 34 | #endif 35 | -------------------------------------------------------------------------------- /libc/include/stdio.h: -------------------------------------------------------------------------------- 1 | #ifndef _STDIO_H 2 | #define _STDIO_H 3 | 4 | typedef struct 5 | { 6 | int fd; 7 | //inode_t *inode; 8 | } FILE; 9 | 10 | #endif 11 | -------------------------------------------------------------------------------- /libc/include/stdlib.h: -------------------------------------------------------------------------------- 1 | #ifndef _STDLIB_H 2 | #define _STDLIB_H 3 | 4 | #include 5 | 6 | #define META_SIZE (2*sizeof(void *) + 1) 7 | #define MIN_TO_SPLIT 1 //min free space required to split the blocks 8 | 9 | void *malloc(size_t); 10 | void free(void *); 11 | void *calloc(size_t, size_t); 12 | 13 | #endif 14 | -------------------------------------------------------------------------------- /libc/include/system.h: -------------------------------------------------------------------------------- 1 | #ifndef _SYSTEM_H 2 | #define _SYSTEM_H 3 | 4 | //#undef __STDC_HOSTED__ 5 | #include 6 | 7 | #define SYS_EXIT 0 8 | #define SYS_OPEN 1 9 | #define SYS_READ 2 10 | #define SYS_WRITE 3 11 | #define SYS_CLOSE 4 12 | #define SYS_FORK 5 13 | #define SYS_EXECVE 6 14 | #define SYS_SBRK 7 15 | #define SYS_GETPID 8 16 | #define SYS_WAIT 9 17 | #define SYS_KILL 10 18 | #define SYS_SIGNAL 11 19 | #define SYS_USLEEP 12 20 | 21 | uint64_t syscall(uint64_t rax, uint64_t rbx, uint64_t rcx, uint64_t rdx); 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /libc/include/unistd.h: -------------------------------------------------------------------------------- 1 | #ifndef _UNISTD_H 2 | #define _UNISTD_H 3 | 4 | #include 5 | 6 | void _exit(uint64_t status); 7 | uint64_t close(uint64_t fd); 8 | uint64_t read(uint64_t fd, void *buf, uint64_t count); 9 | uint64_t write(uint64_t fd, void *buf, uint64_t count); 10 | uint64_t fork(void); 11 | uint64_t execve(uint8_t *path, uint8_t **arg, uint8_t **env); 12 | void *sbrk(uint64_t size); 13 | uint64_t getpid(); 14 | uint64_t wait(uint64_t *status); 15 | uint64_t usleep(uint64_t usec); 16 | 17 | #endif 18 | -------------------------------------------------------------------------------- /libc/src/fcntl.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | uint64_t open(const char *path, uint64_t flags) 6 | { 7 | return syscall(SYS_OPEN, (uint64_t)path, flags, 0); 8 | } 9 | -------------------------------------------------------------------------------- /libc/src/signal.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | sighandler_t *signal(int signum, sighandler_t handler) 7 | { 8 | syscall(SYS_SIGNAL, signum, (uint64_t)handler, 0); 9 | } 10 | 11 | int kill(int pid, int signum) 12 | { 13 | syscall(SYS_KILL, pid, signum, 0); 14 | } 15 | 16 | int raise(int signum) 17 | { 18 | kill(getpid(), signum); 19 | } 20 | -------------------------------------------------------------------------------- /libc/src/stdio.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | -------------------------------------------------------------------------------- /libc/src/stdlib.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | //#include ////printf for debugging 5 | #include 6 | #include 7 | 8 | typedef struct meta_data 9 | { 10 | size_t size; 11 | struct meta_data *next; 12 | uint8_t free; 13 | } __attribute__((packed)) md_t; 14 | 15 | void *malloc(size_t size) 16 | { 17 | char *__ = "\0\0\0\0\0\0\0\0"; // Nasty hack 18 | 19 | void **heap_start = (void**)__; 20 | 21 | /* User Dynamic Memory Allocator "malloc" 22 | * This function is used for dynamic memory allocation 23 | * It uses syscall sbrk() for extending the heap of the program 24 | * 25 | * What this function does ?! 26 | * Nothing ... just basic memory management for the extra area 27 | * It uses first fit alogarithm for finding a free block 28 | * It supports splitting and merging blocks 29 | */ 30 | 31 | if(!*heap_start) { //initializing 32 | 33 | *heap_start = sbrk(META_SIZE + size); 34 | 35 | if(!*heap_start) return NULL; //malloc failed 36 | 37 | ((md_t*) *heap_start)->size = size; 38 | ((md_t*) *heap_start)->next = NULL; 39 | ((md_t*) *heap_start)->free = 0; 40 | 41 | return *heap_start + META_SIZE; 42 | } 43 | //printf("--------------------------------------------------\n"); 44 | //printf("Entered umalloc\n"); 45 | //printf("Size == %u\n",(unsigned) size); 46 | 47 | md_t *prev = NULL; 48 | md_t *current = *heap_start; 49 | md_t *next = NULL; 50 | 51 | while(current) { 52 | if(current->free) { //if current block is free 53 | //printf("Entered if free\n"); 54 | next = current->next; 55 | while(next && next->free) { //Merge blocks 56 | //printf("--------------------\n"); 57 | //printf("Entered Merge\n"); 58 | //printf("Old Size == %u\n",(unsigned) current->size); 59 | //printf("Old Next == 0x%lX\n",(unsigned long) current->next); 60 | current->size = current->size + META_SIZE + next->size; 61 | current->next = next = next->next; 62 | //printf("New Size == %u\n",(unsigned) current->size); 63 | //printf("New Next == 0x%lX\n",(unsigned long) current->next); 64 | } 65 | 66 | if(current->size >= size) break; //found a free block with enough size 67 | } 68 | 69 | prev = current; 70 | current = current->next; //check next block 71 | } 72 | 73 | if(!current) { //if no free blocks found ... extend the heap 74 | //printf("--------------------\n"); 75 | //printf("Entered heap extension\n"); 76 | prev->next = current = sbrk(META_SIZE + size); 77 | 78 | if(!current) return NULL; //malloc failed 79 | 80 | current->size = size; 81 | current->next = NULL; 82 | //current->free = 0; 83 | 84 | //return (void*) current + META_SIZE; 85 | } 86 | else if(current->size >= META_SIZE + size + MIN_TO_SPLIT) { //splittable free block with enough space found 87 | //printf("--------------------\n"); 88 | //printf("Entered split\n"); 89 | //printf("current == 0x%lX\n",(unsigned long)current); 90 | //printf("META_SIZE == 0x%X\n",(unsigned) META_SIZE); 91 | //printf("Size == %u\n",(unsigned) size); 92 | next = (void *) current + META_SIZE + size; 93 | next->size = current->size - size - META_SIZE; 94 | next->next = current->next; 95 | next->free = 1; 96 | 97 | current->size = size; 98 | current->next = next; 99 | //printf("next should be == 0x%lX\n",(unsigned long) current + META_SIZE + size); 100 | //printf("next is == 0x%lX\n",(unsigned long) next); 101 | //current->free = 0; 102 | 103 | //return (void*) current + META_SIZE; 104 | } 105 | //printf("--------------------\n"); 106 | //printf("Entered return stage\n"); 107 | //printf("current == 0x%lX\n",(unsigned long)current); 108 | //printf("META_SIZE == 0x%X\n",(unsigned) META_SIZE); 109 | //printf("should return == 0x%lX\n",(unsigned long) (void*) current + META_SIZE); 110 | //printf("--------------------------------------------------\n"); 111 | current->free = 0; 112 | return (void *) current + META_SIZE; 113 | 114 | } 115 | 116 | void free(void *ptr) 117 | { 118 | /* Very simple free 119 | * TODO: Free block even if ptr is in the middle of the block 120 | */ 121 | ((md_t *) (ptr-META_SIZE))->free = 1; 122 | } 123 | 124 | void *calloc(size_t num_units,size_t size_unit) 125 | { 126 | //TODO:Add overflow check 127 | size_t i = num_units*size_unit; 128 | uint8_t *ptr, *_ptr; 129 | 130 | ptr = _ptr = malloc(i); 131 | if(!ptr) return NULL; 132 | 133 | //Doing it byte by byte since malloc isn't aligned 134 | while(i--) { *_ptr = 0; _ptr++; } 135 | 136 | return ptr; 137 | } 138 | -------------------------------------------------------------------------------- /libc/src/system.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | uint64_t syscall(uint64_t rax, uint64_t rbx, uint64_t rcx, uint64_t rdx) 5 | { 6 | asm("int $0x80;" 7 | : 8 | : "a"(rax), "b"(rbx), "c"(rcx), "d"(rdx) 9 | ); 10 | } 11 | -------------------------------------------------------------------------------- /libc/src/unistd.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | void _exit(uint64_t status) 5 | { 6 | syscall(SYS_EXIT, status, 0 , 0); 7 | } 8 | 9 | uint64_t close(uint64_t fd) 10 | { 11 | return syscall(SYS_CLOSE, fd, 0, 0); 12 | } 13 | 14 | uint64_t read(uint64_t fd, void *buf, uint64_t count) 15 | { 16 | return syscall(SYS_READ, fd, (uint64_t)buf, count); 17 | } 18 | 19 | uint64_t write(uint64_t fd, void *buf, uint64_t count) 20 | { 21 | return syscall(SYS_WRITE, fd, (uint64_t)buf, count); 22 | } 23 | 24 | uint64_t fork(void) 25 | { 26 | return syscall(SYS_FORK, 0, 0, 0); 27 | } 28 | 29 | uint64_t execve(uint8_t *path, uint8_t **arg, uint8_t **env) 30 | { 31 | return syscall(SYS_EXECVE, (uint64_t)path, (uint64_t)arg, (uint64_t)env); 32 | } 33 | 34 | void *sbrk(uint64_t size) 35 | { 36 | return (void*)syscall(SYS_SBRK, size, 0, 0); 37 | } 38 | 39 | uint64_t getpid() 40 | { 41 | return syscall(SYS_GETPID, 0, 0, 0); 42 | } 43 | 44 | uint64_t wait(uint64_t *status) 45 | { 46 | return syscall(SYS_WAIT, (uint64_t)status, 0, 0); 47 | } 48 | 49 | uint64_t usleep(uint64_t usec) 50 | { 51 | return syscall(SYS_USLEEP, (uint64_t)usec, 0, 0); 52 | } 53 | --------------------------------------------------------------------------------