diff options
| author | Aleksa Vučković <aleksav013@gmail.com> | 2021-10-25 00:36:33 +0200 |
|---|---|---|
| committer | Aleksa Vučković <aleksav013@gmail.com> | 2021-10-25 00:36:33 +0200 |
| commit | 20dd72e40dc2728d3c5335d860e4b8ab8da14fcc (patch) | |
| tree | dabdfdf736c45f9632fa1388d2144b1de7a438b0 /src/c | |
| parent | 0bca634f7e70b05239f46f3bd40bb37468d67957 (diff) | |
Changing build system to recursive make
Diffstat (limited to 'src/c')
| -rw-r--r-- | src/c/Makefile | 5 | ||||
| -rw-r--r-- | src/c/gdt.c | 48 | ||||
| -rw-r--r-- | src/c/heap.c | 167 | ||||
| -rw-r--r-- | src/c/idt.c | 101 | ||||
| -rw-r--r-- | src/c/kernel.c | 17 | ||||
| -rw-r--r-- | src/c/keyboard.c | 110 | ||||
| -rw-r--r-- | src/c/keymap.c | 173 | ||||
| -rw-r--r-- | src/c/stdio.c | 37 | ||||
| -rw-r--r-- | src/c/string.c | 113 | ||||
| -rw-r--r-- | src/c/tty.c | 75 | ||||
| -rw-r--r-- | src/c/vga.c | 126 |
11 files changed, 972 insertions, 0 deletions
diff --git a/src/c/Makefile b/src/c/Makefile new file mode 100644 index 0000000..7c5d1af --- /dev/null +++ b/src/c/Makefile @@ -0,0 +1,5 @@ +.PHONY: all +all: $(C_OBJECTS) + +$(BUILD_DIR)/%.o: %.c + $(CC) -c $< -o $@ -std=gnu99 $(CFLAGS) diff --git a/src/c/gdt.c b/src/c/gdt.c new file mode 100644 index 0000000..8fcda3a --- /dev/null +++ b/src/c/gdt.c @@ -0,0 +1,48 @@ +#include"../include/types.h" + +struct gdt_entry +{ + uint16_t limit; + uint16_t base1; + uint8_t base2; + uint8_t access; + uint8_t limit_flags; + uint8_t base3; +} __attribute__((packed)); + +struct gdt_pointer +{ + uint16_t size; + uint32_t offset; +} __attribute__((packed)); + +// asm function +extern void load_gdt(struct gdt_pointer *gdtp); + +struct gdt_entry gdt[3]; +struct gdt_pointer gdtp; + +void init_gdt_entry(size_t num, uint32_t limit, uint32_t base, uint8_t access, uint8_t limit_flags) +{ + gdt[num].limit=limit; + gdt[num].base1=(base & 0xffff); + gdt[num].base2=(base & 0xff0000) >> 16; + gdt[num].access=access; + gdt[num].limit_flags=limit_flags; + gdt[num].base3=(base & 0xff000000) >> 24; +} + +void init_gdt_table() +{ + gdtp.size=sizeof(gdt)-1; + gdtp.offset=(uint32_t)&gdt; + + //null + init_gdt_entry(0,0,0,0,0); + //code + init_gdt_entry(1,0xffffffff,0,0b10011010,0b11001111); + //data + init_gdt_entry(2,0xffffffff,0,0b10010010,0b11001111); + + load_gdt(&gdtp); +} diff --git a/src/c/heap.c b/src/c/heap.c new file mode 100644 index 0000000..1bad05e --- /dev/null +++ b/src/c/heap.c @@ -0,0 +1,167 @@ +#include"../include/types.h" + +/* + 2014 Leonard Kevin McGuire Jr (www.kmcg3413.net) (kmcg3413@gmail.com) + 2016 Clément Gallet (provided bug fixes) +*/ +typedef struct _KHEAPBLOCKBM { + struct _KHEAPBLOCKBM *next; + uint32_t size; + uint32_t used; + uint32_t bsize; + uint32_t lfb; +} KHEAPBLOCKBM; + +typedef struct _KHEAPBM { + KHEAPBLOCKBM *fblock; +} KHEAPBM; + +void k_heapBMInit(KHEAPBM *heap) { + heap->fblock = 0; +} + +int k_heapBMAddBlock(KHEAPBM *heap, uintptr_t addr, uint32_t size, uint32_t bsize) { + KHEAPBLOCKBM *b; + uint32_t bcnt; + uint32_t x; + uint8_t *bm; + + b = (KHEAPBLOCKBM*)addr; + b->size = size - sizeof(KHEAPBLOCKBM); + b->bsize = bsize; + + b->next = heap->fblock; + heap->fblock = b; + + bcnt = b->size / b->bsize; + bm = (uint8_t*)&b[1]; + + /* clear bitmap */ + for (x = 0; x < bcnt; ++x) { + bm[x] = 0; + } + + /* reserve room for bitmap */ + bcnt = (bcnt / bsize) * bsize < bcnt ? bcnt / bsize + 1 : bcnt / bsize; + for (x = 0; x < bcnt; ++x) { + bm[x] = 5; + } + + b->lfb = bcnt - 1; + + b->used = bcnt; + + return 1; +} + +static uint8_t k_heapBMGetNID(uint8_t a, uint8_t b) { + uint8_t c; + for (c = a + 1; c == b || c == 0; ++c); + return c; +} + +void *k_heapBMAlloc(KHEAPBM *heap, uint32_t size) { + KHEAPBLOCKBM *b; + uint8_t *bm; + uint32_t bcnt; + uint32_t x, y, z; + uint32_t bneed; + uint8_t nid; + + /* iterate blocks */ + for (b = heap->fblock; b; b = b->next) { + /* check if block has enough room */ + if (b->size - (b->used * b->bsize) >= size) { + + bcnt = b->size / b->bsize; + bneed = (size / b->bsize) * b->bsize < size ? size / b->bsize + 1 : size / b->bsize; + bm = (uint8_t*)&b[1]; + + for (x = (b->lfb + 1 >= bcnt ? 0 : b->lfb + 1); x < b->lfb; ++x) { + /* just wrap around */ + if (x >= bcnt) { + x = 0; + } + + if (bm[x] == 0) { + /* count free blocks */ + for (y = 0; bm[x + y] == 0 && y < bneed && (x + y) < bcnt; ++y); + + /* we have enough, now allocate them */ + if (y == bneed) { + /* find ID that does not match left or right */ + nid = k_heapBMGetNID(bm[x - 1], bm[x + y]); + + /* allocate by setting id */ + for (z = 0; z < y; ++z) { + bm[x + z] = nid; + } + + /* optimization */ + b->lfb = (x + bneed) - 2; + + /* count used blocks NOT bytes */ + b->used += y; + + return (void*)(x * b->bsize + (uintptr_t)&b[1]); + } + + /* x will be incremented by one ONCE more in our FOR loop */ + x += (y - 1); + continue; + } + } + } + } + + return 0; +} + +void k_heapBMFree(KHEAPBM *heap, void *ptr) { + KHEAPBLOCKBM *b; + uintptr_t ptroff; + uint32_t bi, x; + uint8_t *bm; + uint8_t id; + uint32_t max; + + for (b = heap->fblock; b; b = b->next) { + if ((uintptr_t)ptr > (uintptr_t)b && (uintptr_t)ptr < (uintptr_t)b + sizeof(KHEAPBLOCKBM) + b->size) { + /* found block */ + ptroff = (uintptr_t)ptr - (uintptr_t)&b[1]; /* get offset to get block */ + /* block offset in BM */ + bi = ptroff / b->bsize; + /* .. */ + bm = (uint8_t*)&b[1]; + /* clear allocation */ + id = bm[bi]; + /* oddly.. GCC did not optimize this */ + max = b->size / b->bsize; + for (x = bi; bm[x] == id && x < max; ++x) { + bm[x] = 0; + } + /* update free block count */ + b->used -= x - bi; + return; + } + } + + /* this error needs to be raised or reported somehow */ + return; +} + +KHEAPBM kheap; + +void heap() +{ + KHEAPBM kheap; + char *ptr; + + k_heapBMInit(&kheap); /* initialize the heap */ + k_heapBMAddBlock(&kheap, 0x100000, 0x100000, 16); /* add block to heap + (starting 1MB mark and length of 1MB) + with default block size of 16 bytes + */ + ptr = (char*)k_heapBMAlloc(&kheap, 256); /* allocate 256 bytes (malloc) */ + k_heapBMFree(&kheap, ptr); /* free the pointer (free) */ +} diff --git a/src/c/idt.c b/src/c/idt.c new file mode 100644 index 0000000..274db6d --- /dev/null +++ b/src/c/idt.c @@ -0,0 +1,101 @@ +#include"../include/types.h" + +#define INTERRUPT_GATE_32 0x8e + +#define KERNEL_CODE 0x08 +#define KERNEL_DATA 0x10 + +#define PIC1_COMMAND_PORT 0x20 +#define PIC1_DATA_PORT 0x21 +#define PIC2_COMMAND_PORT 0xA0 +#define PIC2_DATA_PORT 0xA1 + +struct idt_entry +{ + uint16_t offset1; + uint16_t selector; + uint8_t zero; + uint8_t type_attr; + uint16_t offset2; +} __attribute__((packed)); + +struct idt_pointer +{ + uint16_t size; + uint32_t offset; +} __attribute__((packed)); + +// asm function +extern void load_idt(struct idt_pointer *idtp); +extern void keyboard_handler(); +extern void ioport_out(uint8_t port, char data); + +struct idt_entry idt[256]; +struct idt_pointer idtp; + +void init_idt_entry(size_t num, uint32_t offset, uint16_t selector, uint8_t type_attr) +{ + idt[num].offset1=(offset & 0xffff); + idt[num].selector=selector; + idt[num].zero=0; + idt[num].type_attr=type_attr; + idt[num].offset2=(offset & 0xffff0000)>>16; +} + +void init_idt_table() +{ + // Program the PICs - Programmable Interrupt Controllers + // Background: + // In modern architectures, the PIC is not a separate chip. + // It is emulated in the CPU for backwards compatability. + // The APIC (Advanced Programmable Interrupt Controller) + // is the new version of the PIC that is integrated into the CPU. + // Default vector offset for PIC is 8 + // This maps IRQ0 to interrupt 8, IRQ1 to interrupt 9, etc. + // This is a problem. The CPU reserves the first 32 interrupts for + // CPU exceptions such as divide by 0, etc. + // In programming the PICs, we move this offset to 0x2 (32) so that + // we can handle all interrupts coming to the PICs without overlapping + // with any CPU exceptions. + + // Send ICWs - Initialization Command Words + // PIC1: IO Port 0x20 (command), 0xA0 (data) + // PIC2: IO Port 0x21 (command), 0xA1 (data) + // ICW1: Initialization command + // Send a fixed value of 0x11 to each PIC to tell it to expect ICW2-4 + // Restart PIC1 + ioport_out(PIC1_COMMAND_PORT, 0x11); + ioport_out(PIC2_COMMAND_PORT, 0x11); + // ICW2: Vector Offset (this is what we are fixing) + // Start PIC1 at 32 (0x20 in hex) (IRQ0=0x20, ..., IRQ7=0x27) + // Start PIC2 right after, at 40 (0x28 in hex) + ioport_out(PIC1_DATA_PORT, 0x20); + ioport_out(PIC2_DATA_PORT, 0x28); + // ICW3: Cascading (how master/slave PICs are wired/daisy chained) + // Tell PIC1 there is a slave PIC at IRQ2 (why 4? don't ask me - https://wiki.osdev.org/8259_PIC) + // Tell PIC2 "its cascade identity" - again, I'm shaky on this concept. More resources in notes + ioport_out(PIC1_DATA_PORT, 0x0); + ioport_out(PIC2_DATA_PORT, 0x0); + // ICW4: "Gives additional information about the environemnt" + // See notes for some potential values + // We are using 8086/8088 (MCS-80/85) mode + // Not sure if that's relevant, but there it is. + // Other modes appear to be special slave/master configurations (see wiki) + ioport_out(PIC1_DATA_PORT, 0x1); + ioport_out(PIC2_DATA_PORT, 0x1); + // Voila! PICs are initialized + + // Mask all interrupts (why? not entirely sure) + // 0xff is 16 bits that are all 1. + // This masks each of the 16 interrupts for that PIC. + ioport_out(PIC1_DATA_PORT, 0xff); + ioport_out(PIC2_DATA_PORT, 0xff); + + init_idt_entry(0x21,(uint32_t)keyboard_handler,KERNEL_CODE,INTERRUPT_GATE_32); + + idtp.size=sizeof(struct idt_entry)*256-1; + idtp.offset=(uint32_t)&idt; + + + load_idt(&idtp); +} diff --git a/src/c/kernel.c b/src/c/kernel.c new file mode 100644 index 0000000..e18a7c0 --- /dev/null +++ b/src/c/kernel.c @@ -0,0 +1,17 @@ +#include"../include/heap.h" + +void terminal_initialize(void); +void init_idt_table(void); +void init_keyboard(void); +void prompt(void); + +void kernel_main(void) +{ + terminal_initialize(); + init_idt_table(); + init_keyboard(); + k_heapBMInit(&kheap); + + prompt(); + while(1) __asm__("hlt\n\t"); +} diff --git a/src/c/keyboard.c b/src/c/keyboard.c new file mode 100644 index 0000000..548cdda --- /dev/null +++ b/src/c/keyboard.c @@ -0,0 +1,110 @@ +#include"../include/types.h" +#include"../include/asm.h" +#include"../include/stdio.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 + +void previous_field(void); +void terminal_putchar(char c); +void tty(char *buffer); +void prompt(void); +void clear(); +void us_en(char keymap[]); + +char charcode[256]; +bool ispressed[128]; + +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); + us_en(charcode); +} + +void backspace() +{ + if(buffer_index<=0) return; + + previous_field(); + printf(" "); + previous_field(); + buffer[--buffer_index]='\0'; + return; +} + +void enter() +{ + printf("\n"); + if(buffer_index>0) + { + tty(buffer); + for(int i=0;i<BUFFER_SIZE;i++) buffer[i]='\0'; + buffer_index=0; + } + prompt(); + return; +} + +void space() +{ + buffer[buffer_index++]=' '; + printf(" "); +} +#define lshift ispressed[0x2A] +#define lctrl ispressed[0x1D] + +void handle_keyboard_interrupt() +{ + ioport_out(PIC1_COMMAND_PORT, 0x20); + uint8_t status = ioport_in(KEYBOARD_STATUS_PORT); + + if (status & 0x1) + { + uint8_t keycode = ioport_in(KEYBOARD_DATA_PORT); + if(keycode<0x80) + { + ispressed[keycode]=1; + if(keycode==0x0E) backspace(); + else if(keycode==0x1C) enter(); + else if(keycode==0x39) space(); + else + { + char c=charcode[keycode]; + if(c!=' ') + { + if(lshift) + { + if(c>='a'&&c<='z') c-=32; + } + if(lctrl) + { + if(c=='l') + { + clear(); + prompt(); + return; + } + } + buffer[buffer_index++]=c; + printf("%c",c); + } + } + } + else + { + ispressed[keycode-0x80]=0; + } + + } +} diff --git a/src/c/keymap.c b/src/c/keymap.c new file mode 100644 index 0000000..04c79b2 --- /dev/null +++ b/src/c/keymap.c @@ -0,0 +1,173 @@ +void us_en(char keymap[]) +{ + keymap[0x01]=' '; //escape pressed + keymap[0x02]='1'; //1 pressed + keymap[0x03]='2'; //2 pressed + keymap[0x04]='3'; //3 pressed + keymap[0x05]='4'; //4 pressed + keymap[0x06]='4'; //5 pressed + keymap[0x07]='5'; //6 pressed + keymap[0x08]='7'; //7 pressed + keymap[0x09]='8'; //8 pressed + keymap[0x0A]='9'; //9 pressed + keymap[0x0B]='0'; //0 (zero) pressed + keymap[0x0C]='-'; //- pressed + keymap[0x0D]='='; //= pressed + keymap[0x0E]=' '; //backspace pressed + keymap[0x0F]=' '; //tab pressed + keymap[0x10]='q'; //Q pressed + keymap[0x11]='w'; //W pressed + keymap[0x12]='e'; //E pressed + keymap[0x13]='r'; //R pressed + keymap[0x14]='t'; //T pressed + keymap[0x15]='y'; //Y pressed + keymap[0x16]='u'; //U pressed + keymap[0x17]='i'; //I pressed + keymap[0x18]='o'; //O pressed + keymap[0x19]='p'; //P pressed + keymap[0x1A]='['; //[ pressed + keymap[0x1B]=']'; //] pressed + keymap[0x1C]='\n'; //enter pressed + keymap[0x1D]=' '; //left control pressed + keymap[0x1E]='a'; //A pressed + keymap[0x1F]='s'; //S pressed + keymap[0x20]='d'; //D pressed + keymap[0x21]='f'; //F pressed + keymap[0x22]='g'; //G pressed + keymap[0x23]='h'; //H pressed + keymap[0x24]='j'; //J pressed + keymap[0x25]='k'; //K pressed + keymap[0x26]='l'; //L pressed + keymap[0x27]=';'; //; pressed + keymap[0x28]='\''; //' (single quote) pressed + keymap[0x29]='`'; //` (back tick) pressed + keymap[0x2A]=' '; //left shift pressed + keymap[0x2B]='\\'; //\ pressed + keymap[0x2C]='z'; //Z pressed + keymap[0x2D]='x'; //X pressed + keymap[0x2E]='c'; //C pressed + keymap[0x2F]='v'; //V pressed + keymap[0x30]='b'; //B pressed + keymap[0x31]='n'; //N pressed + keymap[0x32]='m'; //M pressed + keymap[0x33]=','; //, pressed + keymap[0x34]='.'; //. pressed + keymap[0x35]='/'; /// pressed + keymap[0x36]=' '; //right shift pressed + keymap[0x37]=' '; //(keypad) * pressed + keymap[0x38]=' '; //left alt pressed + keymap[0x39]=' '; //space pressed + keymap[0x3A]=' '; //CapsLock pressed + keymap[0x3B]=' '; //F1 pressed + keymap[0x3C]=' '; //F2 pressed + keymap[0x3D]=' '; //F3 pressed + keymap[0x3E]=' '; //F4 pressed + keymap[0x3F]=' '; //F5 pressed + keymap[0x40]=' '; //F6 pressed + keymap[0x41]=' '; //F7 pressed + keymap[0x42]=' '; //F8 pressed + keymap[0x43]=' '; //F9 pressed + keymap[0x44]=' '; //F10 pressed + keymap[0x45]=' '; //NumberLock pressed + keymap[0x46]=' '; //ScrollLock pressed + keymap[0x47]='7'; //(keypad) 7 pressed + keymap[0x48]='8'; //(keypad) 8 pressed + keymap[0x49]='9'; //(keypad) 9 pressed + keymap[0x4A]='-'; //(keypad) - pressed + keymap[0x4B]='4'; //(keypad) 4 pressed + keymap[0x4C]='5'; //(keypad) 5 pressed + keymap[0x4D]='6'; //(keypad) 6 pressed + keymap[0x4E]='+'; //(keypad) + pressed + keymap[0x4F]='1'; //(keypad) 1 pressed + keymap[0x50]='2'; //(keypad) 2 pressed + keymap[0x51]='3'; //(keypad) 3 pressed + keymap[0x52]='0'; //(keypad) 0 pressed + keymap[0x53]='.'; //(keypad) . pressed + keymap[0x57]=' '; //F11 pressed + keymap[0x58]=' '; //F12 pressed + keymap[0x81]=' '; //escape released + keymap[0x82]=' '; //1 released + keymap[0x83]=' '; //2 released + keymap[0x84]=' '; //3 released + keymap[0x85]=' '; //4 released + keymap[0x86]=' '; //5 released + keymap[0x87]=' '; //6 released + keymap[0x88]=' '; //7 released + keymap[0x89]=' '; //8 released + keymap[0x8A]=' '; //9 released + keymap[0x8B]=' '; //0 (zero) released + keymap[0x8C]=' '; //- released + keymap[0x8D]=' '; //= released + keymap[0x8E]=' '; //backspace released + keymap[0x8F]=' '; //tab released + keymap[0x90]=' '; //Q released + keymap[0x91]=' '; //W released + keymap[0x92]=' '; //E released + keymap[0x93]=' '; //R released + keymap[0x94]=' '; //T released + keymap[0x95]=' '; //Y released + keymap[0x96]=' '; //U released + keymap[0x97]=' '; //I released + keymap[0x98]=' '; //O released + keymap[0x99]=' '; //P released + keymap[0x9A]=' '; //[ released + keymap[0x9B]=' '; //] released + keymap[0x9C]=' '; //enter released + keymap[0x9D]=' '; //left control released + keymap[0x9E]=' '; //A released + keymap[0x9F]=' '; //S released + keymap[0xA0]=' '; //D released + keymap[0xA1]=' '; //F released + keymap[0xA2]=' '; //G released + keymap[0xA3]=' '; //H released + keymap[0xA4]=' '; //J released + keymap[0xA5]=' '; //K released + keymap[0xA6]=' '; //L released + keymap[0xA7]=' '; //; released + keymap[0xA8]=' '; //' (single quote) released + keymap[0xA9]=' '; //` (back tick) released + keymap[0xAA]=' '; //left shift released + keymap[0xAB]=' '; //\ released + keymap[0xAC]=' '; //Z released + keymap[0xAD]=' '; //X released + keymap[0xAE]=' '; //C released + keymap[0xAF]=' '; //V released + keymap[0xB0]=' '; //B released + keymap[0xB1]=' '; //N released + keymap[0xB2]=' '; //M released + keymap[0xB3]=' '; //, released + keymap[0xB4]=' '; //. released + keymap[0xB5]=' '; /// released + keymap[0xB6]=' '; //right shift released + keymap[0xB7]=' '; //(keypad) * released + keymap[0xB8]=' '; //left alt released + keymap[0xB9]=' '; //space released + keymap[0xBA]=' '; //CapsLock released + keymap[0xBB]=' '; //F1 released + keymap[0xBC]=' '; //F2 released + keymap[0xBD]=' '; //F3 released + keymap[0xBE]=' '; //F4 released + keymap[0xBF]=' '; //F5 released + keymap[0xC0]=' '; //F6 released + keymap[0xC1]=' '; //F7 released + keymap[0xC2]=' '; //F8 released + keymap[0xC3]=' '; //F9 released + keymap[0xC4]=' '; //F10 released + keymap[0xC5]=' '; //NumberLock released + keymap[0xC6]=' '; //ScrollLock released + keymap[0xC7]=' '; //(keypad) 7 released + keymap[0xC8]=' '; //(keypad) 8 released + keymap[0xC9]=' '; //(keypad) 9 released + keymap[0xCA]=' '; //(keypad) - released + keymap[0xCB]=' '; //(keypad) 4 released + keymap[0xCC]=' '; //(keypad) 5 released + keymap[0xCD]=' '; //(keypad) 6 released + keymap[0xCE]=' '; //(keypad) + released + keymap[0xCF]=' '; //(keypad) 1 released + keymap[0xD0]=' '; //(keypad) 2 released + keymap[0xD1]=' '; //(keypad) 3 released + keymap[0xD2]=' '; //(keypad) 0 released + keymap[0xD3]=' '; //(keypad) . released + keymap[0xD7]=' '; //F11 released + keymap[0xD8]=' '; //F12 released +} diff --git a/src/c/stdio.c b/src/c/stdio.c new file mode 100644 index 0000000..83d2b0a --- /dev/null +++ b/src/c/stdio.c @@ -0,0 +1,37 @@ +#include"../include/types.h" +#include"../include/string.h" +#include<stdarg.h> + +void terminal_putchar(char c); +void terminal_writestring(char* data); +void terminal_writeint(uint32_t data); +void terminal_writefloat(double num); + +void printf(char *str, ...) +{ + size_t count=0; + for(size_t i=0;str[i]!='\0';i++) if(str[i]=='%') count++; + + va_list list; + va_start(list, str); + + for(size_t i=0;str[i]!='\0';i++) + { + if(str[i]=='%') + { + i++; + if(str[i]=='c') terminal_putchar((char)va_arg(list,int)); + else if(str[i]=='s') terminal_writestring(va_arg(list,char*)); + else if(str[i]=='d') terminal_writeint(va_arg(list,int)); + else if(str[i]=='f') terminal_writefloat(va_arg(list,double)); + else + { + terminal_writestring("wrong format using print function\n"); + return; + } + } + else terminal_putchar(str[i]); + } + + va_end(list); +} diff --git a/src/c/string.c b/src/c/string.c new file mode 100644 index 0000000..5667715 --- /dev/null +++ b/src/c/string.c @@ -0,0 +1,113 @@ +#include"../include/types.h" + +size_t stringlen(char *str) +{ + size_t i; + + for(i=0;str[i]!='\0';i++) ; + + return i; +} + +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; +} + +void stringcat(char *str1,char *str2) +{ + char *tmp=str1; + while(*tmp) tmp++; + while(*str2) *tmp++=*str2++; + *tmp=*str2; +} + +void stringcpy(char *str1,char *str2) +{ + for(size_t i=0;str2[i]!='\0';i++) str1[i]=str2[i]; +} + +void stringrev(char *str) +{ + size_t i=stringlen(str)-1; + + for(size_t j=0;j<i-j;j++) + { + char tmp=str[i-j]; + str[i-j]=str[j]; + str[j]=tmp; + } +} + +uint32_t stoi(const char *str) +{ + uint32_t num=0; + + for(size_t i=0;str[i]!='\0';i++) + { + if(str[i]<'0'||str[i]>'9') return num; + num*=10; + num+=str[i]-'0'; + } + + return num; +} + +void itos(uint32_t num,char *str) +{ + if(num==0) stringcpy(str,"0"); + else + { + size_t i=0; + for(;num>0;num/=10,i++) str[i]='0'+num%10; + str[i]='\0'; + + stringrev(str); + } +} + +double stof(const char *str) +{ + double num=0; + + bool point=0; + uint32_t pow=1; + size_t i=0; + + for(;str[i]!='\0';i++) + { + if(str[i]=='.') + { + if(point) return num/pow; + point=1; + continue; + } + if(str[i]<'0'||str[i]>'9') return num/pow; + num*=10; + num+=str[i]-'0'; + if(point) pow*=10; + } + + return num/pow; +} + +const int decimals=7; +void ftos(double num, char *str) +{ + itos((uint32_t)num,str); + + stringcat(str,"."); + char c[2]; + c[1]='\0'; + + for(size_t i=0;i<decimals;i++) + { + num-=(uint32_t)num; + num*=10; + c[0]=(uint32_t)num+'0'; + stringcat(str,c); + } +} diff --git a/src/c/tty.c b/src/c/tty.c new file mode 100644 index 0000000..5728a47 --- /dev/null +++ b/src/c/tty.c @@ -0,0 +1,75 @@ +#include"../include/types.h" +#include"../include/string.h" +#include"../include/stdio.h" + +#define CMD_LENGTH 20 + +void clear(); + +size_t pieces(char pieces[][CMD_LENGTH],char *buffer) +{ + for(size_t x=0;x<CMD_LENGTH;x++) for(size_t y=0;y<CMD_LENGTH;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; +} + +void echo(size_t numberof,char parts[][CMD_LENGTH]) +{ + for(size_t i=1;i<numberof;i++) + { + printf("%s ",parts[i]); + } + printf("\n"); +} + +void merge(char parts[][CMD_LENGTH]) +{ + char *str1=parts[1]; + char *str2=parts[2]; + stringcat(str1,str2); + printf("%s\n",str1); +} + +void ls(size_t numberof,char parts[][CMD_LENGTH]) +{ + printf("filesystem not implemented yet, %d,%s\n",numberof,parts[0]); +} + +void number(size_t numberof,char parts[][CMD_LENGTH]) +{ + if(numberof==1) printf("Please enter a number\n"); + else + { + printf("number times two is %d\n",2*stoi(parts[1])); + printf("number times two is %f\n",2*stof(parts[1])); + } +} + +void tty(char *buffer) +{ + char parts[CMD_LENGTH][CMD_LENGTH]; + size_t numberof=pieces(parts,buffer); + + if(stringcmp(parts[0],"clear")) clear(); + else if(stringcmp(parts[0],"echo")) echo(numberof,parts); + else if(stringcmp(parts[0],"merge")) merge(parts); + else if(stringcmp(parts[0],"ls")) ls(numberof,parts); + else if(stringcmp(parts[0],"number")) number(numberof,parts); + else printf("command not found: %s\n",parts[0]); +} diff --git a/src/c/vga.c b/src/c/vga.c new file mode 100644 index 0000000..07dec60 --- /dev/null +++ b/src/c/vga.c @@ -0,0 +1,126 @@ +#include"../include/types.h" +#include"../include/string.h" +#include"../include/asm.h" + +static const size_t VGA_WIDTH = 80; +static const size_t VGA_HEIGHT = 25; + + +enum vga_color { + VGA_COLOR_BLACK = 0, + VGA_COLOR_BLUE = 1, + VGA_COLOR_GREEN = 2, + VGA_COLOR_CYAN = 3, + VGA_COLOR_RED = 4, + VGA_COLOR_MAGENTA = 5, + VGA_COLOR_BROWN = 6, + VGA_COLOR_LIGHT_GREY = 7, + VGA_COLOR_DARK_GREY = 8, + VGA_COLOR_LIGHT_BLUE = 9, + VGA_COLOR_LIGHT_GREEN = 10, + VGA_COLOR_LIGHT_CYAN = 11, + VGA_COLOR_LIGHT_RED = 12, + VGA_COLOR_LIGHT_MAGENTA = 13, + VGA_COLOR_LIGHT_BROWN = 14, + VGA_COLOR_WHITE = 15, +}; + +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(char* data) +{ + for(int i=0;data[i]!='\0';i++) terminal_putchar(data[i]); +} + +void terminal_writeint(uint32_t num) +{ + char string[100]; + for(int i=0;i<100;i++) string[i]='\0'; + char *str=string; + itos(num,str); + terminal_writestring(str); +} + +void terminal_writefloat(double num) +{ + char string[100]; + for(int i=0;i<100;i++) string[i]='\0'; + char *str=string; + ftos(num,str); + terminal_writestring(str); +} + +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; +} |
