diff options
| author | Aleksa Vučković <aleksav013@gmail.com> | 2021-10-12 21:53:40 +0200 |
|---|---|---|
| committer | Aleksa Vučković <aleksav013@gmail.com> | 2021-10-12 21:53:40 +0200 |
| commit | 4528b2347ac72ffdabdbe4d9e7bf7789c81e664f (patch) | |
| tree | 7a5b14e228d858def22d0b5bfcffba69c4e5879e | |
| parent | 578d467b80015c52d0c96c8443b4c13936f33365 (diff) | |
Adding tty
| -rw-r--r-- | Makefile | 4 | ||||
| -rw-r--r-- | src/boot.s | 5 | ||||
| -rw-r--r-- | src/kernel.c | 128 | ||||
| -rw-r--r-- | src/keyboard.c | 78 | ||||
| -rw-r--r-- | src/keyboard.h | 4 | ||||
| -rw-r--r-- | src/string.c | 34 | ||||
| -rw-r--r-- | src/tty.c | 32 | ||||
| -rw-r--r-- | src/vga.c | 93 |
8 files changed, 250 insertions, 128 deletions
@@ -2,7 +2,7 @@ ARCH=i686-elf CC=$(ARCH)-gcc AS=$(ARCH)-as -CFLAGS=-ffreestanding -O2 -Wall -Wextra -ggdb +CFLAGS=-ffreestanding -O2 -Wall -Wextra MKDIR=mkdir -p RM=rm -rf @@ -15,7 +15,7 @@ ISO_DIR=isodir TARGET=myos -OBJ_FILES=boot.o kernel.o gdt.o idt.o +OBJ_FILES=boot.o kernel.o gdt.o idt.o keyboard.o vga.o string.o tty.o CRTBEGIN_OBJ=$(shell $(CC) -print-file-name=crtbegin.o) CRTEND_OBJ=$(shell $(CC) -print-file-name=crtend.o) OBJ=$(BUILD_DIR)/crti.o $(CRTBEGIN_OBJ) $(patsubst %,$(BUILD_DIR)/%,$(OBJ_FILES)) $(CRTEND_OBJ) $(BUILD_DIR)/crtn.o @@ -64,8 +64,9 @@ stack_top: .type _start, @function _start: call init_gdt_table - ljmp $CODE_SEGMENT, $next - next: + ljmp $CODE_SEGMENT, $code + +code: movw $DATA_SEGMENT, %ax movw %ax, %ds movw %ax, %es diff --git a/src/kernel.c b/src/kernel.c index 0882580..0ad3b66 100644 --- a/src/kernel.c +++ b/src/kernel.c @@ -1,129 +1,13 @@ -#include<stdbool.h> -#include<stddef.h> -#include<stdint.h> -#include"vga.h" - -static const size_t VGA_WIDTH = 80; -static const size_t VGA_HEIGHT = 25; - -#define PIC1_COMMAND_PORT 0x20 -#define PIC1_DATA_PORT 0x21 -#define PIC2_COMMAND_PORT 0xA0 -#define PIC2_DATA_PORT 0xA1 -// IO Ports for Keyboard -#define KEYBOARD_DATA_PORT 0x60 -#define KEYBOARD_STATUS_PORT 0x64 - -extern char ioport_in(uint8_t port); -extern void ioport_out(uint8_t port, char data); - -static inline uint8_t vga_entry_color(enum vga_color fg, enum vga_color bg) -{ - return fg | bg << 4; -} - -static inline uint16_t vga_entry(unsigned char uc, uint8_t color) -{ - return (uint16_t) uc | (uint16_t) color << 8; -} - -size_t terminal_row; -size_t terminal_column; -uint8_t terminal_color; -uint16_t* terminal_buffer; - -void terminal_initialize(void) -{ - terminal_row=0; - terminal_column=0; - terminal_color=vga_entry_color(VGA_COLOR_LIGHT_GREY, VGA_COLOR_BLACK); - terminal_buffer=(uint16_t*) 0xB8000; - for(size_t y=0;y<VGA_HEIGHT;y++) - { - for(size_t x=0;x<VGA_WIDTH;x++) - { - const size_t index=y*VGA_WIDTH+x; - terminal_buffer[index]=vga_entry(' ', terminal_color); - } - } -} - -void terminal_putentryat(char c, uint8_t color, size_t x, size_t y) -{ - const size_t index=y*VGA_WIDTH+x; - terminal_buffer[index]=vga_entry(c, color); -} - -void movescreen() -{ - terminal_row--; - for(size_t i=0;i<VGA_HEIGHT;i++) for(size_t j=0;j<VGA_WIDTH;j++) terminal_buffer[i*VGA_WIDTH+j]=terminal_buffer[(i+1)*VGA_WIDTH+j]; -} - -void terminal_putchar(char c) -{ - if(c=='\n') terminal_column = 0,terminal_row++; - else - { - terminal_putentryat(c, terminal_color, terminal_column, terminal_row); - if (++terminal_column==VGA_WIDTH) terminal_column=0,terminal_row++; - } - if (terminal_row==VGA_HEIGHT) movescreen(); -} - -void terminal_writestring(const char* data) -{ - for(int i=0;data[i]!='\0';i++) terminal_putchar(data[i]); -} - -void init_keyboard() -{ - // 0xFD = 1111 1101 in binary. enables only IRQ1 - // Why IRQ1? Remember, IRQ0 exists, it's 0-based - ioport_out(PIC1_DATA_PORT, 0xFD); -} - -#include"keyboard.h" -void handle_keyboard_interrupt() -{ - // Write end of interrupt (EOI) - ioport_out(PIC1_COMMAND_PORT, 0x20); - unsigned char status = ioport_in(KEYBOARD_STATUS_PORT); - - // Lowest bit of status will be set if buffer not empty - // (thanks mkeykernel) - if (status & 0x1) - { - char keycode = ioport_in(KEYBOARD_DATA_PORT); - if (keycode < 0 || (uint8_t)keycode >= 128) return; - - if(keycode==14) - { - if(terminal_column) terminal_column--; - terminal_putchar(keyboard[keycode]); - terminal_column--; - return; - } - - terminal_putchar(keyboard[keycode]); - - } -} -void print_message() -{ - for(size_t i=0;i<50;i++) - { - for(size_t j=0;j<i;j++) terminal_writestring("#"); - terminal_writestring("Hello, kernel World!\n"); - } -} +void terminal_initialize(void); +void init_idt_table(void); +void init_keyboard(void); +void prompt(void); void kernel_main(void) { terminal_initialize(); - print_message(); init_idt_table(); init_keyboard(); - terminal_writestring("First part is working\n"); - while(1); + prompt(); + while(1) __asm__("hlt\n\t"); } diff --git a/src/keyboard.c b/src/keyboard.c new file mode 100644 index 0000000..987c7a2 --- /dev/null +++ b/src/keyboard.c @@ -0,0 +1,78 @@ +#include<stdbool.h> +#include<stddef.h> +#include<stdint.h> +#include"keyboard.h" + +#define BUFFER_SIZE 200 +char buffer[BUFFER_SIZE]; +size_t buffer_index=0; + +#define PIC1_COMMAND_PORT 0x20 +#define PIC1_DATA_PORT 0x21 +#define PIC2_COMMAND_PORT 0xA0 +#define PIC2_DATA_PORT 0xA1 +// IO Ports for Keyboard +#define KEYBOARD_DATA_PORT 0x60 +#define KEYBOARD_STATUS_PORT 0x64 + +extern char ioport_in(uint8_t port); +extern void ioport_out(uint8_t port, char data); + +void previous_field(); +void terminal_putchar(char c); +void tty(char *buffer); +void prompt(); + +void init_keyboard() +{ + // 0xFD = 1111 1101 in binary. enables only IRQ1 + // Why IRQ1? Remember, IRQ0 exists, it's 0-based + ioport_out(PIC1_DATA_PORT, 0xFD); +} + +void backspace() +{ + if(buffer_index<=0) return; + + previous_field(); + terminal_putchar(' '); + previous_field(); + buffer[--buffer_index]='\0'; + return; +} + +void enter() +{ + terminal_putchar('\n'); + if(buffer_index>0) + { + tty(buffer); + for(int i=0;i<BUFFER_SIZE;i++) buffer[i]='\0'; + buffer_index=0; + } + prompt(); + return; +} + +void handle_keyboard_interrupt() +{ + // Write end of interrupt (EOI) + ioport_out(PIC1_COMMAND_PORT, 0x20); + unsigned char status = ioport_in(KEYBOARD_STATUS_PORT); + + // Lowest bit of status will be set if buffer not empty + if (status & 0x1) + { + int16_t keycode = ioport_in(KEYBOARD_DATA_PORT); + if (keycode < 0 || keycode >= 128) return; + + if(keycode==14) backspace(); + else if(keycode==28) enter(); + else + { + buffer[buffer_index++]=keyboard[keycode]; + terminal_putchar(keyboard[keycode]); + } + + } +} diff --git a/src/keyboard.h b/src/keyboard.h index 53846e6..5de7e10 100644 --- a/src/keyboard.h +++ b/src/keyboard.h @@ -6,11 +6,11 @@ unsigned char keyboard[128] = { // -------- 10 to 19 -------- '9','0','-','=', ' ', // Backspace - ' ', // Tab + ' ', // Tab 'q','w','e','r', // -------- 20 to 29 -------- 't','y','u','i','o','p','[',']', - '\n', // Enter + ' ', // Enter ' ', // left Ctrl // -------- 30 to 39 -------- 'a','s','d','f','g','h','j','k','l',';', diff --git a/src/string.c b/src/string.c new file mode 100644 index 0000000..4683470 --- /dev/null +++ b/src/string.c @@ -0,0 +1,34 @@ +#include<stdbool.h> +#include<stddef.h> +#include<stdint.h> + +bool stringcmp(char *str1,char *str2) +{ + size_t i; + for(i=0;str1[i]||str2[i];i++) if(str1[i]!=str2[i]) return 0; + if(str1[i]==str2[i]) return 1; + return 0; +} + +size_t pieces(char pieces[15][15],char *buffer) +{ + for(size_t x=0;x<15;x++) for(size_t y=0;y<15;y++) pieces[x][y]='\0'; + + size_t i=0,j=0,r=0; + while(buffer[i]==' '&&buffer[i]!='\0') i++; + for(;buffer[i]!='\0';i++) + { + if(buffer[i]==' ') + { + while(buffer[i]==' '&&buffer[i]!='\0') i++; + j=0; + r++; + i--; + } + else + { + pieces[r][j++]=buffer[i]; + } + } + return r+1; +} diff --git a/src/tty.c b/src/tty.c new file mode 100644 index 0000000..c3fe295 --- /dev/null +++ b/src/tty.c @@ -0,0 +1,32 @@ +#include<stdbool.h> +#include<stddef.h> +#include<stdint.h> +bool stringcmp(char *str1,char *str2); +size_t pieces(char pieces[][15],char *buffer); +void clear(); +void terminal_writestring(const char* data); +void terminal_putchar(char c); + +void echo(size_t numberof,char parts[][15]) +{ + for(size_t i=1;i<numberof;i++) + { + terminal_writestring(parts[i]); + terminal_putchar(' '); + } + terminal_putchar('\n'); +} + +void tty(char *buffer) +{ + char parts[15][15]; + size_t numberof=pieces(parts,buffer); + if(stringcmp(parts[0],"clear")) clear(); + else if(stringcmp(parts[0],"echo")) echo(numberof,parts); + else + { + terminal_writestring("command not found: "); + terminal_writestring(parts[0]); + terminal_putchar('\n'); + } +} diff --git a/src/vga.c b/src/vga.c new file mode 100644 index 0000000..71faa1a --- /dev/null +++ b/src/vga.c @@ -0,0 +1,93 @@ +#include<stdbool.h> +#include<stddef.h> +#include<stdint.h> +#include"vga.h" +static const size_t VGA_WIDTH = 80; +static const size_t VGA_HEIGHT = 25; + +extern char ioport_in(uint8_t port); +extern void ioport_out(uint8_t port, char data); + +bool stringcmp(char *str1,char *str2); + +static inline uint8_t vga_entry_color(enum vga_color fg, enum vga_color bg) +{ + return fg | bg << 4; +} + +static inline uint16_t vga_entry(unsigned char uc, uint8_t color) +{ + return (uint16_t) uc | (uint16_t) color << 8; +} + +size_t terminal_row; +size_t terminal_column; +uint8_t terminal_color; +uint16_t* terminal_buffer; + +void terminal_initialize() +{ + terminal_row=0; + terminal_column=0; + terminal_color=vga_entry_color(VGA_COLOR_LIGHT_GREY, VGA_COLOR_BLACK); + terminal_buffer=(uint16_t*) 0xB8000; + for(size_t y=0;y<VGA_HEIGHT;y++) + { + for(size_t x=0;x<VGA_WIDTH;x++) + { + const size_t index=y*VGA_WIDTH+x; + terminal_buffer[index]=vga_entry(' ', terminal_color); + } + } +} + +void terminal_putentryat(char c, uint8_t color, size_t x, size_t y) +{ + const size_t index=y*VGA_WIDTH+x; + terminal_buffer[index]=vga_entry(c, color); +} + +void movescreen() +{ + terminal_row--; + for(size_t i=0;i<VGA_HEIGHT;i++) for(size_t j=0;j<VGA_WIDTH;j++) terminal_buffer[i*VGA_WIDTH+j]=terminal_buffer[(i+1)*VGA_WIDTH+j]; +} + +void next_field() +{ + if(++terminal_column==VGA_WIDTH) terminal_column=0,terminal_row++; +} + +void previous_field() +{ + if(terminal_column) terminal_column--; + else terminal_row--,terminal_column=VGA_WIDTH-1; +} + +void terminal_putchar(char c) +{ + if(c=='\n') terminal_column=0,terminal_row++; + else + { + terminal_putentryat(c, terminal_color, terminal_column, terminal_row); + next_field(); + } + if (terminal_row==VGA_HEIGHT) movescreen(); +} + +void terminal_writestring(const char* data) +{ + for(int i=0;data[i]!='\0';i++) terminal_putchar(data[i]); +} + +void prompt() +{ + terminal_writestring("[user@myos] > "); +} + +void clear() +{ + for(size_t i=0;i<VGA_HEIGHT;i++) for(size_t j=0;j<VGA_WIDTH;j++) terminal_putchar(' '); + terminal_column=0; + terminal_row=0; +} |
