From da5fc52afe7f64467a1acefb337338f671a59c62 Mon Sep 17 00:00:00 2001 From: Xnoe Date: Mon, 16 May 2022 09:57:09 +0100 Subject: [PATCH] Updated the KernelInformationStruct, added BGA (Bochs Graphics Extensions) mode termimal, added new system calls to get terminal width. Updated world.bin to calculate sizes. Fixed a bug where GetExhaustive would crash when given a completely null path. Started work on V86 for VBE support. --- Makefile | 4 +- src/boot/boot.asm | 2 +- src/bootstage2/main.c | 18 +++-- src/bootstage2/paging.c | 39 +++++++++ src/common/syscalls.h | 5 +- src/kernel/entry.asm | 1 - src/kernel/filesystem/fstree.cpp | 2 + src/kernel/gdt.cpp | 28 ++++--- src/kernel/gdt.h | 5 ++ src/kernel/gen_isr_asm.sh | 3 + src/kernel/global.cpp | 1 + src/kernel/global.h | 1 + src/kernel/idt.cpp | 87 ++++++++++++++++++-- src/kernel/idt.h | 35 ++++++++ src/kernel/kernel.cpp | 58 +++++++++++++ src/kernel/kernel.h | 4 +- src/kernel/kmain.cpp | 17 ++-- src/kernel/terminal.cpp | 135 ++++++++++++++++++++++++++++--- src/kernel/terminal.h | 32 +++++++- src/programs/world/world.c | 134 ++++++++++++++++-------------- 20 files changed, 495 insertions(+), 116 deletions(-) diff --git a/Makefile b/Makefile index a698177..f5751de 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ -CFLAGS = -g -std=gnu11 -m32 -mgeneral-regs-only -nostdlib -fno-builtin -fno-exceptions -fno-leading-underscore -fno-pie -fno-stack-protector -Wno-pointer-to-int-cast -Isrc/ -CXXFLAGS = -g -m32 -fno-use-cxa-atexit -mgeneral-regs-only -nostdlib -fno-builtin -fno-rtti -fno-exceptions -fno-leading-underscore -fpermissive -fno-pie -fno-stack-protector -Isrc/ +CFLAGS = -g -w -std=gnu11 -m32 -mgeneral-regs-only -nostdlib -fno-builtin -fno-exceptions -fno-leading-underscore -fno-pie -fno-stack-protector -Wno-pointer-to-int-cast -Isrc/ +CXXFLAGS = -g -w -m32 -fno-use-cxa-atexit -mgeneral-regs-only -nostdlib -fno-builtin -fno-rtti -fno-exceptions -fno-leading-underscore -fpermissive -fno-pie -fno-stack-protector -Isrc/ LDFLAGS = DISK_IMG_FILES = build/kernel/kernel.bin hello.txt alpha.txt diff --git a/src/boot/boot.asm b/src/boot/boot.asm index fd9a94a..22b0140 100644 --- a/src/boot/boot.asm +++ b/src/boot/boot.asm @@ -50,7 +50,7 @@ bootcode: mov ax, 2 ; Begin with the 2nd sector call prep_i13 - mov al, 31 ; Load the next 9 sectors (4.5k) + mov al, 31 ; Load the next 31 sectors (15.5kb) int 13h ; We need to get the memory configuration from the BIOS now diff --git a/src/bootstage2/main.c b/src/bootstage2/main.c index b53d7be..f829ee9 100644 --- a/src/bootstage2/main.c +++ b/src/bootstage2/main.c @@ -146,7 +146,7 @@ void main() { map_many_4k_phys_to_virt(0xa0000, 0xc07a0000, kernel_page_directory, kernel_page_tables, 0x20); // Map 32 pages from 0xa0000 to 0xa0000 mark_unavailble(0xa0000, 0x20000, bitmap); - + uint8_t* vm_bitmap = 0x522000; mark_unavailble(vm_bitmap, 0x20000, bitmap); @@ -173,18 +173,22 @@ void main() { map_many_4k_phys_to_virt(0x8a000, 0xc1000000, kernel_page_directory, kernel_page_tables, 16); mark_unavailble(0x8a000, 0x10000, bitmap); - load_file("KERNEL BIN", kernel_location); + // Identity map the first 1MiB of RAM + mark_unavailble(0, 0x100000, bitmap); + mark_unavailble(0, 0x100000, vm_bitmap); + map_many_4k_phys_to_virt_pl3(0, 0, kernel_page_directory, kernel_page_tables, 256); - //while (1); + load_file("KERNEL BIN", kernel_location); asm volatile("mov %0, %%eax;" "mov %%eax, %%cr3;" "mov %%cr0, %%eax;" "or $0x80000000, %%eax;" "mov %%eax, %%cr0" : : "m" (kernel_page_directory)); + + asm volatile ("mov %0, %%esp":: "r"(0xc1000000 + 16*0x1000)); - KernelInformationStruct* kstruct = 0xc1000000 + 16*0x1000 - sizeof(KernelInformationStruct); - *kstruct = (KernelInformationStruct){ + KernelInformationStruct kstruct= (KernelInformationStruct){ .pde = 0xc0100000, .page_directory_phys_addr = kernel_page_directory, .page_directory_phys_offset = 0xc0100000 - (uint32_t)kernel_page_directory, @@ -195,7 +199,5 @@ void main() { .remainingPages = pages }; - *(uint32_t*)(0xc100a004) = kstruct; - - ((void(*)())0xc0000000)(); + ((void(*)(KernelInformationStruct))0xc0000000)(kstruct); } \ No newline at end of file diff --git a/src/bootstage2/paging.c b/src/bootstage2/paging.c index 63978d3..38f6a46 100644 --- a/src/bootstage2/paging.c +++ b/src/bootstage2/paging.c @@ -6,6 +6,40 @@ typedef struct { uint32_t pd_index : 10; }__attribute__((packed)) split_addr; +void map_4k_phys_to_virt_pl3(uint32_t physical, uint32_t virtual, PDE* page_directory, PTE** page_tables) { + split_addr* split = (split_addr*)&virtual; + + page_directory[split->pd_index] = (PDE){ + .address = (uint32_t)(page_tables[split->pd_index]) >> 12, + .available = 0, + .page_4mb = 0, + .accessed = 0, + .disable_cache = 0, + .write_through_cache = 0, + .privilege = 3, + .present = 1, + .read_write = 1, + + .ignored = 0, + .ignored2 = 0 + }; + + page_tables[split->pd_index][split->pt_index] = (PTE){ + .address = physical >> 12, + .available = 0, + .global = 0, + .accessed = 0, + .disable_cache = 0, + .dirty = 0, + .write_through_cache = 0, + .privilege = 3, + .present = 1, + .read_write = 1, + + .ignored = 0 + }; +} + void map_4k_phys_to_virt(uint32_t physical, uint32_t virtual, PDE* page_directory, PTE** page_tables) { split_addr* split = (split_addr*)&virtual; @@ -40,6 +74,11 @@ void map_4k_phys_to_virt(uint32_t physical, uint32_t virtual, PDE* page_director }; } +void map_many_4k_phys_to_virt_pl3(uint32_t physical, uint32_t virtual, PDE* page_directory, PTE** page_tables, uint32_t count) { + for (int i=0; inode; + if (!currentPath) + return 0; if (currentPath->elem != currentNode->self) return 0; while (currentPath && currentNode) { diff --git a/src/kernel/gdt.cpp b/src/kernel/gdt.cpp index 8664685..eb6c291 100644 --- a/src/kernel/gdt.cpp +++ b/src/kernel/gdt.cpp @@ -38,7 +38,7 @@ tss_struct tss = (tss_struct) { .ldtr = 0, ._reserved10 = 0, ._reserved11 = 0, - .iopb = 104 + .iopb = sizeof(tss_struct) }; constexpr gdt_entry::gdt_entry(uint32_t limit, uint32_t base, bool rw, bool exec, bool system, uint8_t ring) : @@ -77,25 +77,29 @@ constexpr gdt_entry::gdt_entry() : base_hi(0) {} -gdt_entry gdt[] = { - gdt_entry(), // Null Segment - gdt_entry(0xfffff, 0, 1, 1, 1, 0), // Kernel Code Segment - gdt_entry(0xfffff, 0, 1, 0, 1, 0), // Kernel Data Segment +gdt_and_iopb gai = { + .gdt = { + gdt_entry(), // Null Segment + gdt_entry(0xfffff, 0, 1, 1, 1, 0), // Kernel Code Segment + gdt_entry(0xfffff, 0, 1, 0, 1, 0), // Kernel Data Segment - gdt_entry(0xfffff, 0, 1, 1, 1, 3), // User Code Segment - gdt_entry(0xfffff, 0, 1, 0, 1, 3), // User Data Segment + gdt_entry(0xfffff, 0, 1, 1, 1, 3), // User Code Segment + gdt_entry(0xfffff, 0, 1, 0, 1, 3), // User Data Segment - gdt_entry() // Empty Task State Segment + gdt_entry() // Empty Task State Segment + } }; gdt_descr descr = (gdt_descr){ - .size = sizeof(gdt) - 1, - .offset = gdt, + .size = sizeof(gai.gdt) - 1, + .offset = gai.gdt, }; void init_gdt() { - gdt[5] = gdt_entry(sizeof(tss), &tss, 0, 1, 0, 0); // Initialise the TSS. - gdt[5].accessed = 1; + gai.gdt[5] = gdt_entry(sizeof(tss) + 8193, &tss, 0, 1, 0, 0); // Initialise the TSS. + gai.gdt[5].accessed = 1; + for (int i=0; i<8192; i++) + gai.iopb[i] = 0; asm volatile("lgdt %0;" "mov $0x10, %%eax;" "mov %%eax, %%ss;" diff --git a/src/kernel/gdt.h b/src/kernel/gdt.h index cac9f3a..2592117 100644 --- a/src/kernel/gdt.h +++ b/src/kernel/gdt.h @@ -76,6 +76,11 @@ struct __attribute__((packed)) gdt_descr { uint32_t offset; }; +struct __attribute__((packed)) gdt_and_iopb { + gdt_entry gdt[6]; + uint8_t iopb[8192]; +}; + void init_gdt(); #endif \ No newline at end of file diff --git a/src/kernel/gen_isr_asm.sh b/src/kernel/gen_isr_asm.sh index e5c0aa8..616fb5a 100755 --- a/src/kernel/gen_isr_asm.sh +++ b/src/kernel/gen_isr_asm.sh @@ -7,6 +7,9 @@ for i ({0..255}); do echo "isr$i:" >> isr.S echo " push ebp" >> isr.S echo " mov ebp, esp" >> isr.S + if (( (i == 8 || i == 17 || (i >= 10 && i <= 14) ) )); then + echo " add ebp, 4" >> isr.S + fi if (( !(i == 8 || i == 17 || (i >= 10 && i <= 14) ) )); then echo " push 0" >> isr.S fi diff --git a/src/kernel/global.cpp b/src/kernel/global.cpp index 36ad57f..032acde 100644 --- a/src/kernel/global.cpp +++ b/src/kernel/global.cpp @@ -8,6 +8,7 @@ namespace Global { bool currentProcValid = false; xnoe::hashtable* FH; // Map of File Handlers -> Read Writer uint32_t milliseconds_elapsed = 0; + uint32_t resp = 0; } void* operator new (uint32_t size) { diff --git a/src/kernel/global.h b/src/kernel/global.h index 04ed1c7..8c30a33 100644 --- a/src/kernel/global.h +++ b/src/kernel/global.h @@ -21,6 +21,7 @@ namespace Global { extern bool currentProcValid; extern xnoe::hashtable* FH; extern uint32_t milliseconds_elapsed; + extern uint32_t resp; } void* operator new (uint32_t size); diff --git a/src/kernel/idt.cpp b/src/kernel/idt.cpp index 04c016d..902f94c 100644 --- a/src/kernel/idt.cpp +++ b/src/kernel/idt.cpp @@ -26,25 +26,29 @@ void handle_fault(frame_struct* frame) { asm ("cli"); uint32_t problem_address; asm ("mov %%cr2, %0" : "=a" (problem_address):); - /*Global::kernel->terminal->printf("\x1b[44;37;1m(CS %x EIP %x): ", frame->cs, frame->eip); + /*Global::kernel->terminal->printf("\x1b[44;37;1m(CS %x EIP %x): ", frame->cs, frame->eip);*/ switch (frame->gate) { case 0: // Divide by zero - Global::kernel->terminal->printf("Divide by Zero"); + //Global::kernel->terminal->printf("Divide by Zero"); break; case 6: // Invalid Opcode - Global::kernel->terminal->printf("Invalid Opcode"); + //Global::kernel->terminal->printf("Invalid Opcode"); break; case 13: // GPF - Global::kernel->terminal->printf("General Protection Fault!"); + //Global::kernel->terminal->printf("General Protection Fault!"); + if (frame->eflags & 0x00020000) { + v86_monitor((v8086_frame_struct*)frame); + return; + } break; case 14: // Page Fault - Global::kernel->terminal->printf("Page Fault at %x", problem_address); + //Global::kernel->terminal->printf("Page Fault at %x", problem_address); break; default: - Global::kernel->terminal->printf("Unkown Fault!"); + //Global::kernel->terminal->printf("Unkown Fault!"); break; } - Global::kernel->terminal->printf(" Error Code: %x\n", frame->errcode);*/ + /*Global::kernel->terminal->printf(" Error Code: %x\n", frame->errcode);*/ if (!(frame->cs & 3)) { Global::kernel->terminal->printf("[FATAL] Kernel Fault!!!\n"); while (1) asm("hlt"); @@ -194,6 +198,12 @@ void syscall(frame_struct* frame) { // 18: sleep :: int time ms -> void // Sleeps the current process for time milliseconds. + // 19: getInitPages :: void -> uint_32 // Returns the amount of physical pages available at boot. + // 20: getRemainingPages :: void -> uint_32 // Returns the amount of physical pages remaining. + + // 21: getCurrentTerminalWidth :: void -> uint32_t // Gets the width of the current terminal + // 22: getCurrentTerminalHeight :: void -> uint32_t // Gets the height of the current terminal + // File handlers: // 0: Stdout // 1: Stdin @@ -362,6 +372,13 @@ void syscall(frame_struct* frame) { rval = Global::kernel->phys->initPages; break; + case 21: + rval = Global::kernel->terminal->width; + break; + case 22: + rval = Global::kernel->terminal->height; + break; + default: break; } @@ -369,6 +386,60 @@ void syscall(frame_struct* frame) { frame->eax = rval; } +void v86_monitor(v8086_frame_struct* frame) { + uint8_t* ip = (uint8_t*)((frame->cs<<4) + frame->eip); + uint16_t* sp = (uint16_t*)frame->esp; + uint16_t flags = (uint16_t)frame->eflags; + switch (*ip) { + case 0x9c: + *(--sp) = (uint16_t)frame->eflags; + frame->eip++; + break; + case 0x9d: + frame->eflags &= 0xffff0000; + frame->eflags |= *(sp++); + frame->eip++; + break; + case 0xcd: { + // Handle int + if (!ip[1]) { + asm("mov %0, %%esp"::"a"(Global::resp)); + asm("popa"); + asm("ret"); + } + uint32_t vector_data = *(uint32_t*)(ip[1]<<2); + *(--sp) = flags; + frame->eflags &= ~(0x00040300); + *(--sp) = (uint16_t)frame->cs; + *(--sp) = (uint16_t)(frame->eip+2); + uint16_t* vector = (uint16_t*)&vector_data; + frame->cs = vector[1]; + frame->eip = (uint32_t)vector[0]; + break; + } + case 0xcf: { + // Handle iret + frame->eip = *(sp++); + frame->cs = *(sp++); + frame->eflags &= 0xffff0000; + frame->eflags |= *(sp++); + break; + } + case 0xfa: + asm("cli"); + frame->eip++; + break; + case 0xfb: + asm("sti"); + frame->eip++; + break; + default: { + break; + } + } + frame->esp = sp; +} + void init_idt() { idt_desc desc = {.size = 256 * sizeof(GateEntry) - 1, .offset = (uint32_t)idt}; asm volatile("lidt %0" : : "m" (desc)); @@ -379,7 +450,6 @@ void init_idt() { for (int i=0; i<256; i++) gates[i] = &ignore_interrupt; - gates[32] = &Timer::tick; gates[0] = &handle_fault; gates[5] = &handle_fault; gates[6] = &handle_fault; @@ -424,5 +494,6 @@ void init_idt() { } void enable_idt() { + gates[32] = &Timer::tick; asm ("sti"); } \ No newline at end of file diff --git a/src/kernel/idt.h b/src/kernel/idt.h index bbdb32e..c61d94c 100644 --- a/src/kernel/idt.h +++ b/src/kernel/idt.h @@ -28,9 +28,43 @@ struct __attribute__((packed)) frame_struct { uint16_t cs; uint16_t _ignored0; uint32_t eflags; + uint32_t esp; uint16_t ss; uint16_t _ignored1; +}; + +struct __attribute__((packed)) v8086_frame_struct { + uint32_t new_cr3; + uint32_t new_esp; + + uint32_t edi; + uint32_t esi; + uint32_t ebp; + uint32_t oesp; + uint32_t ebx; + uint32_t edx; + uint32_t ecx; + uint32_t eax; + + uint32_t gate; + uint32_t __ignored2; + uint32_t errcode; + + uint32_t eip; + uint16_t cs; + uint16_t _ignored0; + uint32_t eflags; uint32_t esp; + uint16_t ss; + uint16_t _ignored1; + uint16_t es; + uint16_t _ignored2; + uint16_t ds; + uint16_t _ignored3; + uint16_t fs; + uint16_t _ignored4; + uint16_t gs; + uint16_t _ignored5; }; extern void(*gates[256])(frame_struct*); @@ -60,5 +94,6 @@ void context_switch(frame_struct* frame); void handle_fault(frame_struct* frame); void syscall(frame_struct* frame); void ignore_interrupt(frame_struct* frame); +void v86_monitor(v8086_frame_struct* frame); #endif \ No newline at end of file diff --git a/src/kernel/kernel.cpp b/src/kernel/kernel.cpp index 13b3926..55472b9 100644 --- a/src/kernel/kernel.cpp +++ b/src/kernel/kernel.cpp @@ -51,4 +51,62 @@ int Kernel::mapFH(ReadWriter* fh) { void Kernel::unmapFH(uint32_t fh) { Global::FH->remove((void*)fh); +} + +void Kernel::v86(uint16_t ax, uint16_t bx, uint16_t cx, uint16_t es, uint16_t di, uint8_t intn) { + // Create the payload to perform an interrupt. + uint8_t payload[21] = { + 0xb8, 0x00, 0x00, // mov ax, 0 + 0x8e, 0xc0, // mov es, ax + 0xb8, 0x00, 0x00, // mov ax, 0 + 0xbb, 0x00, 0x00, // mov bx, 0 + 0xb9, 0x00, 0x00, // mov cx, 0 + 0xbf, 0x00, 0x00, // mov di, 0 + 0xcd, 0x00, // int 0 + 0xcd, 0x00 // int 0 + }; + + // Set the values in the payload. + uint16_t* ax1 = (uint16_t*)(payload+1); + uint16_t* ax2 = (uint16_t*)(payload+6); + uint16_t* bx1 = (uint16_t*)(payload+9); + uint16_t* cx1 = (uint16_t*)(payload+12); + uint16_t* di1 = (uint16_t*)(payload+15); + uint8_t* intn1 = (uint8_t*)(payload+18); + + *ax1 = es; + *ax2 = ax; + *bx1 = bx; + *cx1 = cx; + *di1 = di; + *intn1 = intn; + + // Construct a stack. + uint32_t* stack = 0x9000; + + *(--stack) = 0; // GS + *(--stack) = 0; // FS + *(--stack) = 0; // DS + *(--stack) = 0; // ES + *(--stack) = 0; // SS + *(--stack) = 0x9000; // ESP + *(--stack) = 0x00020000; // EFLAGS + *(--stack) = 0; // CS + *(--stack) = 0x7c00; // EIP + + // Copy 19 bytes from payload to 0x7c00 + + memcpy(payload, (uint8_t*)0x7c00, 21); + + asm("lea _after_iret, %eax"); + asm("push %eax"); + asm("pusha"); + asm("mov %%esp, %0":"=m"(Global::resp)::); + + asm("xor %eax, %eax; xor %ebx, %ebx; xor %ecx, %ecx; xor %edi, %edi"); + + asm("mov %0, %%esp"::"m"(stack):); + asm("iret"); + + asm("_after_iret:"); } \ No newline at end of file diff --git a/src/kernel/kernel.h b/src/kernel/kernel.h index 3d72b4d..9154254 100644 --- a/src/kernel/kernel.h +++ b/src/kernel/kernel.h @@ -6,6 +6,7 @@ #include "global.h" #include "terminal.h" #include "filesystem/fstree.h" +#include "gdt.h" class Kernel : public Process { private: @@ -33,7 +34,8 @@ public: int mapFH(ReadWriter* fh); void unmapFH(uint32_t fh); - //void loadPrimaryStack(); + + void v86(uint16_t ax, uint16_t bx, uint16_t cx, uint16_t es, uint16_t di, uint8_t intn); }; #endif \ No newline at end of file diff --git a/src/kernel/kmain.cpp b/src/kernel/kmain.cpp index e1c2c8d..b4a349a 100644 --- a/src/kernel/kmain.cpp +++ b/src/kernel/kmain.cpp @@ -28,21 +28,20 @@ struct KernelInformationStruct { uint32_t remainingPages; }; -int main(KernelInformationStruct* kstruct) { +int main(KernelInformationStruct kstruct) { init_gdt(); - PageDirectory kernel_pd = PageDirectory(kstruct->pde, kstruct->page_directory_phys_addr, kstruct->page_directory_phys_offset); + PageDirectory kernel_pd = PageDirectory(kstruct.pde, kstruct.page_directory_phys_addr, kstruct.page_directory_phys_offset); kernel_pd.select(); - kernel_pd.unmap(0x8000); - PageMap phys_pm(kstruct->page_bitmap_phys, kstruct->remainingPages); - PageMap virt_pm(kstruct->page_bitmap_virt); + PageMap phys_pm(kstruct.page_bitmap_phys, kstruct.remainingPages); + PageMap virt_pm(kstruct.page_bitmap_virt); - Kernel kernel = Kernel(&kernel_pd, &phys_pm, &virt_pm, 0xc0000000, kstruct->stack_ptr); + Kernel kernel = Kernel(&kernel_pd, &phys_pm, &virt_pm, 0xc0000000, kstruct.stack_ptr); kernel.init_kernel(); - VGAModeTerminal* term = new VGAModeTerminal(kstruct->vga_addr); + VGAModeTerminal* term = new VGAModeTerminal(kstruct.vga_addr); kernel.terminal = term; @@ -72,6 +71,10 @@ int main(KernelInformationStruct* kstruct) { Process* p1 = kernel.createProcess(fh, term); + Global::tss->esp0 = (new uint8_t[8192]) + 8192; + + //kernel.v86(0x4f00,0,0,0x0,0x8000,0x10); + init_keyboard(); if (worldbin) { worldbin->seek(0); diff --git a/src/kernel/terminal.cpp b/src/kernel/terminal.cpp index 7e29c0f..6c3e6aa 100644 --- a/src/kernel/terminal.cpp +++ b/src/kernel/terminal.cpp @@ -200,6 +200,9 @@ void Terminal::putchar(uint8_t c) { this->edata &= 0x0f; this->edata |= (n-40)<<4; break; + case 49: + this->edata &= 0x0f; + this->edata |= 0xf0; default: break; } @@ -235,6 +238,21 @@ Terminal::Terminal(uint32_t width, uint32_t height, uint32_t pages) this->active = false; } +void Terminal::resize(uint32_t width, uint32_t height, uint32_t pages) { + delete this->buffer; + this->width = width; + this->height = height; + this->pages = pages; + this->buffer = new uint16_t[width * height * pages]; + this->last_page_pointer = buffer + (width * height * pages) - (width * height); + this->current_page_pointer = last_page_pointer; + + this->cur_x = 0; + this->cur_y = 0; + + this->active = false; +} + void Terminal::printf(const char* string, ...) { va_list ptr; va_start(ptr, string); @@ -354,6 +372,25 @@ TextModeTerminal::TextModeTerminal(uint16_t* text_mode_pointer): Terminal(80, 25 this->text_mode_pointer = text_mode_pointer; } +uint32_t color_map[16] = { + 0, // Black + 0x00000080, // Blue + 0x00008000, // Green + 0x00008080, // Cyan + 0x00800000, // Red + 0x00800080, // Magenta + 0x00008080, // Yellow + 0x00808080, // White + 0x00404040, // Black + 0x000000ff, // Blue + 0x0000ff00, // Green + 0x0000ffff, // Cyan + 0x000000ff, // Red + 0x00ff00ff, // Magenta + 0x00ffff00, // Yellow + 0x00ffffff // White +}; + void VGAModeTerminal::update() { for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { @@ -382,7 +419,7 @@ void VGAModeTerminal::putchar_internal(uint32_t ptr, uint8_t c, uint8_t edata) { } void VGAModeTerminal::put_pixels_byte(uint32_t x, uint32_t y, uint8_t color, uint8_t pixel_byte) { - uint32_t pixel = y * 720 + x; + uint32_t pixel = y * pixelWidth + x; uint32_t pixelindex = pixel / 8; uint8_t trbyte = 0; @@ -403,7 +440,7 @@ void VGAModeTerminal::put_pixels_byte(uint32_t x, uint32_t y, uint8_t color, uin void VGAModeTerminal::put_pixel(uint32_t x, uint32_t y, uint8_t color) { // For any pixel we need to write 1 bit to planes 0, 1, 2, and 3 - uint32_t pixel = y * 720 + x; + uint32_t pixel = y * pixelWidth + x; uint32_t pixelindex = pixel / 8; uint32_t pixelbitindex = pixel % 8; @@ -416,7 +453,7 @@ void VGAModeTerminal::put_pixel(uint32_t x, uint32_t y, uint8_t color) { } static void VGAModeTerminal::bufferToVRAM(frame_struct* frame, VGAModeTerminal* terminal) { - uint32_t count4 = (720 * 480) / 8 / 4; + uint32_t count4 = (terminal->pixelWidth * terminal->pixelHeight) / 8 / 4; for (int i=0; i<4; i++) { outb(0x3c4, 2); outb(0x3c5, 1<vga_pointer = vga_pointer; - for (int i=0; i<4; i++) { +for (int i=0; i<4; i++) { this->planes[i] = new uint8_t[720 * 480 / 8]; } + this->resize(pixelWidth / 8, pixelHeight / 8, 1); + unsigned char g_720x480x16[] = { - /* MISC */ 0xE7, - /* SEQ */ 0x03, 0x01, 0x08, 0x00, 0x06, - /* CRTC */ 0x6B, 0x59, 0x5A, 0x82, 0x60, 0x8D, 0x0B, 0x3E, 0x00, 0x40, 0x06, 0x07, 0x00, 0x00, 0x00, 0x00, 0xEA, 0x0C, 0xDF, 0x2D, 0x08, 0xE8, 0x05, 0xE3, 0xFF, - /* GC */ 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x05, 0x0F, 0xFF, - /* AC */ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x01, 0x00, 0x0F, 0x00, 0x00, @@ -501,4 +535,85 @@ VGAModeTerminal::VGAModeTerminal(uint8_t* vga_pointer): Terminal(90, 60, 1) { } Timer::register_event(16, &VGAModeTerminal::bufferToVRAM, this); +} + +void BGAModeTerminal::update() { + for (int y = 0; y < height; y++) { + for (int x = 0; x < width; x++) { + putchar_internal(y * width + x, (uint8_t)(current_page_pointer[y * width + x]), (uint8_t)(current_page_pointer[y * width + x]>>8)); + } + } +} + +void BGAModeTerminal::update_cur() { + // Todo: Implement cursor for VGAModeTerminal +} + +void BGAModeTerminal::putchar_internal(uint32_t ptr, uint8_t c, uint8_t edata) { + uint32_t col = ptr % width; + uint32_t row = ptr / width; + + uint32_t sx = col * 8; + uint32_t sy = row * 8; + + if (c>127) + return; + uint8_t* char_data = font[c]; + + for (int y=0; y<8; y++) + put_pixels_byte(sx, sy+y, edata, char_data[y]); +} + +void BGAModeTerminal::put_pixels_byte(uint32_t x, uint32_t y, uint8_t color, uint8_t pixel_byte) { + uint32_t pixel = y * pixelWidth + x; + + for (int i=0; i<8; i++) + if (pixel_byte&(1<fb[pixel+i] = color_map[color&0xf]; + else + this->fb[pixel+i] = color_map[(color>>4)&0xf]; +} + +void BGAModeTerminal::put_pixel(uint32_t x, uint32_t y, uint8_t color) { + // For any pixel we need to write 1 bit to planes 0, 1, 2, and 3 + + uint32_t pixel = y * pixelWidth + x; + uint32_t pixelindex = pixel / 8; + uint32_t pixelbitindex = pixel % 8; + + this->fb[pixel] = color_map[color]; +} + +static void BGAModeTerminal::bufferToVRAM(frame_struct* frame, BGAModeTerminal* terminal) { + uint32_t c = terminal->pixelWidth * terminal->pixelHeight; + uint32_t bank=0; + uint32_t ctr=0; + for (int i=0; ivga_pointer)[i%16384] = ((uint32_t*)terminal->fb)[i]; + } +} + +BGAModeTerminal::BGAModeTerminal(uint8_t* vga_pointer): Terminal(0, 0, 1) { + this->vga_pointer = vga_pointer; + + this->fb = new uint32_t[pixelWidth * pixelHeight]; + + this->resize(pixelWidth / 8, pixelHeight / 8, 1); + + outw(0x1ce, 4); + outw(0x1cf, 0); + outw(0x1ce, 1); + outw(0x1cf, pixelWidth); + outw(0x1ce, 2); + outw(0x1cf, pixelHeight); + outw(0x1ce, 3); + outw(0x1cf, 32); + outw(0x1ce, 4); + outw(0x1cf, 1); + + Timer::register_event(16, &BGAModeTerminal::bufferToVRAM, this); } \ No newline at end of file diff --git a/src/kernel/terminal.h b/src/kernel/terminal.h index 598ab69..a894ae6 100644 --- a/src/kernel/terminal.h +++ b/src/kernel/terminal.h @@ -46,8 +46,6 @@ private: protected: uint16_t* buffer; - uint32_t width; - uint32_t height; uint32_t pages; uint32_t cur_x; @@ -59,7 +57,12 @@ protected: bool active; uint8_t edata=0x07; + void resize(uint32_t width, uint32_t height, uint32_t pages); + public: + uint32_t width; + uint32_t height; + Terminal(uint32_t width, uint32_t height, uint32_t pages); void printf(const char* string, ...); @@ -88,7 +91,6 @@ public: TextModeTerminal(uint16_t* text_mode_pointer); }; - class VGAModeTerminal : public Terminal { private: void update() override; @@ -101,9 +103,33 @@ private: static void bufferToVRAM(frame_struct* frame, VGAModeTerminal* terminal); public: + uint32_t pixelWidth = 720; + uint32_t pixelHeight = 480; + uint8_t* vga_pointer; uint8_t* planes[4]; VGAModeTerminal(uint8_t* vga_pointer); }; + +class BGAModeTerminal : public Terminal { +private: + void update() override; + void update_cur() override; + void putchar_internal(uint32_t ptr, uint8_t c,uint8_t edata) override; + + void put_pixel(uint32_t x, uint32_t y, uint8_t color); + void put_pixels_byte(uint32_t x, uint32_t y, uint8_t color, uint8_t pixel_byte); + + static void bufferToVRAM(frame_struct* frame, BGAModeTerminal* terminal); + +public: + uint32_t pixelWidth = 720; + uint32_t pixelHeight = 480; + + uint8_t* vga_pointer; + uint32_t* fb; + + BGAModeTerminal(uint8_t* vga_pointer); +}; #endif \ No newline at end of file diff --git a/src/programs/world/world.c b/src/programs/world/world.c index 12a1cf3..5578e23 100644 --- a/src/programs/world/world.c +++ b/src/programs/world/world.c @@ -8,15 +8,17 @@ typedef struct { uint32_t process; uint32_t stdin; uint32_t stdout; + uint32_t width; + uint32_t height; } procbuffer; -void scrollBuffer(char* buf) { - for (int y=0; y<56; y++) - for (int x=0; x<43; x++) - if (y != 55) - buf[y*43+x] = buf[(y+1)*43+x]; +void scrollBuffer(procbuffer* buf) { + for (int y=0; yheight; y++) + for (int x=0; xwidth; x++) + if (y != buf->height-1) + buf->buffer[y*buf->width+x] = buf->buffer[(y+1)*buf->width+x]; else - buf[y*43+x] = ' '; + buf->buffer[y*buf->width+x] = ' '; } void writeToBuf(char c, procbuffer* buf) { @@ -30,22 +32,22 @@ void writeToBuf(char c, procbuffer* buf) { if (buf->x > 0) buf->x--; else if (buf->y > 0) { - buf->x = 42; + buf->x = buf->width-1; buf->y--; } - buf->buffer[buf->y*43+buf->x] = ' '; + buf->buffer[buf->y*buf->width+buf->x] = ' '; break; default: - buf->buffer[buf->y*43+buf->x++] = c; + buf->buffer[buf->y*buf->width+buf->x++] = c; } - if (buf->x == 43) { + if (buf->x == buf->width) { buf->x = 0; buf->y++; } - if (buf->y == 56) { + if (buf->y == buf->height) { buf->y--; - scrollBuffer(buf->buffer); + scrollBuffer(buf); } } @@ -56,7 +58,7 @@ void writeCountToBuf(int count, char* c, procbuffer* buf) { } void clearBuf(procbuffer* buf) { - for (int i=0; i<56*43;i++) { + for (int i=0; iheight*buf->width;i++) { buf->buffer[i] = ' '; } buf->x = 0; @@ -69,53 +71,42 @@ void writeStrToBuf(char* c, procbuffer* b) { writeToBuf(*(s++), b); } -void displayBuf(procbuffer* b, int dx, int dy) { - print("\x1b[42;36;1m"); - char pset[9] = "\x1b[00;00H"; - for (int i=0; ibuffer+(43*i)); - pset[3]++; - if (pset[3] == 0x3a) { - pset[3] = 0x30; - pset[2]++; - } - } -} - void setCurPos(int x, int y) { - char pset[9] = "\x1b[00;00H"; + char pset[11] = "\x1b[000;000H"; for (int i=0; iheight; i++) { + setCurPos(dx, dy++); + write(b->width, 0, b->buffer+(b->width*i)); + } +} + void readline(int count, char* buffer) { int index = 0; char c; @@ -161,6 +152,12 @@ bool strcmpcnt(int count, char* a, char* b) { } int main() { + int width = getCurrentTerminalWidth(); + int height = getCurrentTerminalHeight(); + + int bufferWidth = (width - 4) / 2; + int bufferHeight = (height - 4); + bindToKeyboard(); char space = ' '; @@ -172,16 +169,25 @@ int main() { print("\x1b[1;1H"); print("\x1b[45;33;1m"); - char* mid = "+ ++ +"; - char* bottom = "+ +"; - for (int i=0; i<90;i++) + for (int i=0; i