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.

This commit is contained in:
Xnoe 2022-05-16 09:57:09 +01:00
parent 6339b3e4bd
commit da5fc52afe
Signed by: xnoe
GPG Key ID: 45AC398F44F0DAFE
20 changed files with 495 additions and 116 deletions

View File

@ -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

View File

@ -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

View File

@ -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);
}

View File

@ -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; i<count; i++)
map_4k_phys_to_virt_pl3(physical + 4096*i, virtual + 4096*i, page_directory, page_tables);
}
void map_many_4k_phys_to_virt(uint32_t physical, uint32_t virtual, PDE* page_directory, PTE** page_tables, uint32_t count) {
for (int i=0; i<count; i++)
map_4k_phys_to_virt(physical + 4096*i, virtual + 4096*i, page_directory, page_tables);

View File

@ -21,4 +21,7 @@ syscall_hdlr_1(void, kill, "17", uint32_t, PID);
syscall_hdlr_1(void, sleep, "18", uint32_t, time);
syscall_hdlr_0(uint32_t, getRemainingPages, "19");
syscall_hdlr_0(uint32_t, getInitPages, "20");
syscall_hdlr_0(uint32_t, getInitPages, "20");
syscall_hdlr_0(uint32_t, getCurrentTerminalWidth, "21");
syscall_hdlr_0(uint32_t, getCurrentTerminalHeight, "22");

View File

@ -1,7 +1,6 @@
[BITS 32]
_start:
mov esp, 0xc100a000
jmp main
extern main

View File

@ -125,6 +125,8 @@ Path* RootFSTree::getRemainingPath(Path p) {
FSTreeNode* RootFSTree::getExhaustive(Path p) {
PathElement* currentPath = p.start;
FSTreeNode* currentNode = this->node;
if (!currentPath)
return 0;
if (currentPath->elem != currentNode->self)
return 0;
while (currentPath && currentNode) {

View File

@ -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;"

View File

@ -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

View File

@ -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

View File

@ -8,6 +8,7 @@ namespace Global {
bool currentProcValid = false;
xnoe::hashtable<void*, ReadWriter*>* FH; // Map of File Handlers -> Read Writer
uint32_t milliseconds_elapsed = 0;
uint32_t resp = 0;
}
void* operator new (uint32_t size) {

View File

@ -21,6 +21,7 @@ namespace Global {
extern bool currentProcValid;
extern xnoe::hashtable<void*, ReadWriter*>* FH;
extern uint32_t milliseconds_elapsed;
extern uint32_t resp;
}
void* operator new (uint32_t size);

View File

@ -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");
}

View File

@ -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

View File

@ -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:");
}

View File

@ -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

View File

@ -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);

View File

@ -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<<i);
@ -427,28 +464,25 @@ static void VGAModeTerminal::bufferToVRAM(frame_struct* frame, VGAModeTerminal*
}
}
VGAModeTerminal::VGAModeTerminal(uint8_t* vga_pointer): Terminal(90, 60, 1) {
VGAModeTerminal::VGAModeTerminal(uint8_t* vga_pointer): Terminal(0, 0, 1) {
this->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<<i))
this->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; i<c; i++) {
if (i%16384 == 0) {
outw(0x1ce, 5);
outw(0x1cf, bank++);
}
((uint32_t*)terminal->vga_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);
}

View File

@ -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

View File

@ -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; y<buf->height; y++)
for (int x=0; x<buf->width; 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; i<buf->height*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; i<dy;i++) {
pset[3]++;
if (pset[3] == 0x3a) {
pset[3] = 0x30;
pset[2]++;
}
}
for (int i=0; i<dx;i++) {
pset[6]++;
if (pset[6] == 0x3a) {
pset[6] = 0x30;
pset[5]++;
}
}
for (int i=0; i<56; i++) {
print(pset);
write(43, 0, b->buffer+(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; i<y;i++) {
pset[3]++;
pset[4]++;
if (pset[4] == 0x3a) {
pset[4] = 0x30;
pset[3]++;
}
if (pset[3] == 0x3a) {
pset[3] = 0x30;
pset[2]++;
}
}
for (int i=0; i<x;i++) {
pset[6]++;
if (pset[6] == 0x3a) {
pset[6] = 0x30;
pset[5]++;
pset[8]++;
if (pset[8] == 0x3a) {
pset[8] = 0x30;
pset[7]++;
}
if (pset[7] == 0x3a) {
pset[7] = 0x30;
pset[6]++;
}
}
print(pset);
}
void displayBuf(procbuffer* b, int dx, int dy) {
print("\x1b[42;36;1m");
char pset[9] = "\x1b[000;000H";
for (int i=0; i<b->height; 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<width;i++)
write(1, 0, &plus);
for (int i=0; i<56;i++)
write(90, 0, mid);
for (int i=0; i<90;i++)
for (int i=0; i<bufferHeight;i++) {
write(1, 0, &plus);
write(90, 0, bottom);
for (int i=0; i<90;i++)
for (int j=0; j<bufferWidth; j++)
write(1, 0, &space);
write(1, 0, &plus);
write(1, 0, &plus);
for (int j=0; j<bufferWidth; j++)
write(1, 0, &space);
write(1, 0, &plus);
}
for (int i=0; i<width;i++)
write(1, 0, &plus);
write(1, 0, &plus);
for (int i=0; i< width - 2; i++)
write(1, 0, &space);
write(1, 0, &plus);
for (int i=0; i<width;i++)
write(1, 0, &plus);
uint32_t program = fopen("/hello.bin");
@ -196,21 +202,25 @@ int main() {
fclose(program);
procbuffer b1 = {
.buffer = malloc(56 * 43),
.buffer = malloc(bufferWidth * bufferHeight),
.x = 0,
.y = 0,
.process = p1,
.stdin = p1in,
.stdout = p1out
.stdout = p1out,
.width = bufferWidth,
.height = bufferHeight
};
procbuffer b2 = {
.buffer = malloc(56 * 43),
.buffer = malloc(bufferWidth * bufferHeight),
.x = 0,
.y = 0,
.process = p2,
.stdin = p2in,
.stdout = p2out
.stdout = p2out,
.width = bufferWidth,
.height = bufferHeight
};
procbuffer* selectedBuf = &b1;
@ -230,9 +240,9 @@ int main() {
if (c[0] == ':') {
char buf[32] = {0};
print("\x1b[45;33;1m");
print("\x1b[59;2H");
setCurPos(2, height-1);
print(": ");
print("\x1b[59;3H");
setCurPos(3, height-1);
readline(32, buf);
if (strcmpcnt(6, buf, "switch")) {
if (selectedBuf == &b1) {
@ -293,6 +303,6 @@ int main() {
}
displayBuf(&b1, 2, 2);
displayBuf(&b2, 47, 2);
displayBuf(&b2, bufferWidth+4, 2);
}
}