diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/kernel/boot.asm | 4 | ||||
-rw-r--r-- | src/kernel/graphics/vesa.c | 134 | ||||
-rw-r--r-- | src/kernel/graphics/vesa.h | 18 | ||||
-rw-r--r-- | src/kernel/interact.asm | 8 | ||||
-rw-r--r-- | src/kernel/io/io.c | 8 | ||||
-rw-r--r-- | src/kernel/kernel.c | 6 | ||||
-rw-r--r-- | src/kernel/paging/kheap.h | 4 | ||||
-rw-r--r-- | src/kernel/paging/paging.c | 12 | ||||
-rw-r--r-- | src/kernel/paging/paging.h | 12 |
9 files changed, 129 insertions, 77 deletions
diff --git a/src/kernel/boot.asm b/src/kernel/boot.asm index 97e68f5..de5a386 100644 --- a/src/kernel/boot.asm +++ b/src/kernel/boot.asm @@ -54,7 +54,7 @@ copy_page_physical: and edx, 0x7fffffff mov cr0, edx - mov edx, 1024 + mov edx, 0x400 %include "src/kernel/gdt/gdt.asm" @@ -68,5 +68,5 @@ copy_page_physical: ; Store the stack SECTION .bss - resb 8192 ; Reserve 8KiB + resb 0x2000 ; Reserve 8KiB _sys_stack:
\ No newline at end of file diff --git a/src/kernel/graphics/vesa.c b/src/kernel/graphics/vesa.c index d19e7d8..3c55f70 100644 --- a/src/kernel/graphics/vesa.c +++ b/src/kernel/graphics/vesa.c @@ -5,6 +5,9 @@ #include "../paging/kheap.h" #include "../io/io.h" #include "font.h" +#include "../paging/paging.h" + +extern page_directory_t *kernel_directory; void switch_to_vga() { serial_write("Force switch to VGA!\n"); @@ -29,92 +32,111 @@ struct edid_data get_edid() { return *edid; } -struct vbe_mode_info *vbe_set_mode(unsigned short mode) { - serial_write("Setting VBE mode!\n"); +void vbe_set_mode(unsigned short mode) { + serial_write("Setting VBE mode: "); + serial_write_hex(mode); + serial_write("\n"); vesa_available = 0; regs16_t regs; regs.ax = 0x4F02; + regs.bx = mode; regs.bx = mode | (1 << 14); + disable_paging(); int32(0x10, ®s); + enable_paging(); - if (regs.ax == 0x004F) { - regs.ax = 0x4F01; - regs.cx = mode; - regs.es = 0xA000; - regs.di = 0x0000; - int32(0x10, ®s); - if (regs.ax != 0x004F) { - switch_to_vga(); - return ((void *) 0); - } - - struct vbe_mode_info *vbe_info = (struct vbe_mode_info *) 0xA0000; - - vbe_width = vbe_info->width; - vbe_height = vbe_info->height; - vbe_bpp = vbe_info->bpp / 8; - vbe_pitch = vbe_info->pitch; - fb = (char *) vbe_info->framebuffer; - - /*for (int i = 0; i < vbe_width * vbe_height * vbe_bpp; i++) { - fb[i] = 100; - fb[i + 1] = 100; - fb[i + 2] = 100; - }*/ - - vesa_available = 1; - - return vbe_info; - } else { - switch_to_vga(); - return ((void *) 0); - } + if (regs.ax != 0x004F) switch_to_vga(); + else vesa_available = 1; } -void set_optimal_resolution() { +uint16_t *vbe_get_modes() { vesa_available = 0; - struct vbe_info *info = (struct vbe_info *) 0x2000; - struct vbe_mode_info *mode_info = (struct vbe_mode_info *) 0x3000; - - memory_copy(info->signature, "VBE2", 4); + char *info_address = (char *) 0x7E00; + strcpy(info_address, "VBE2"); + for (int i = 4; i < 512; i++) *(info_address + i) = 0; regs16_t regs; regs.ax = 0x4F00; regs.es = 0; - regs.di = 0x2000; + regs.di = 0x7E00; + disable_paging(); int32(0x10, ®s); + enable_paging(); + + struct vbe_info *info = (struct vbe_info *) info_address; if (regs.ax != 0x004F || strcmp(info->signature, "VESA") != 0) { switch_to_vga(); - return; + return ((void *) 0); } + // Get number of modes uint16_t *mode_ptr = get_ptr(info->video_modes); - uint16_t mode; + int number_modes = 1; + for (uint16_t *p = mode_ptr; *p != 0xFFFF; p++) number_modes++; + + uint16_t *video_modes = (uint16_t *) kmalloc(sizeof(uint16_t) * number_modes); + for (int i = 0; i < number_modes; i++) + video_modes[i] = mode_ptr[i]; + + return video_modes; +} + +struct vbe_mode_info *vbe_get_mode_info(uint16_t mode) { + regs16_t regs; + regs.ax = 0x4F01; + regs.cx = mode; + regs.es = 0; + regs.di = 0x7E00; + disable_paging(); + int32(0x10, ®s); + enable_paging(); + + struct vbe_mode_info_all *mode_info = (struct vbe_mode_info_all *) 0x7E00; + struct vbe_mode_info *mode_info_final = (struct vbe_mode_info *) kmalloc(sizeof(struct vbe_mode_info)); + mode_info_final->attributes = mode_info->attributes; + mode_info_final->width = mode_info->width; + mode_info_final->height = mode_info->height; + mode_info_final->bpp = mode_info->bpp; + mode_info_final->pitch = mode_info->pitch; + mode_info_final->memory_model = mode_info->memory_model; + mode_info_final->framebuffer = mode_info->framebuffer; + + return mode_info_final; +} + +void set_optimal_resolution() { + uint16_t *video_modes = vbe_get_modes(); uint16_t highest = 0x11B; uint16_t highest_width = 0; - while ((mode = *mode_ptr++) != 0xFFFF) { - mode &= 0x1FF; - regs16_t regs2; - regs2.ax = 0x4F01; - regs2.cx = mode; - regs2.es = get_segment(mode_info); - regs2.di = get_offset(mode_info); - int32(0x10, ®s2); - - if ((mode_info->attributes & 0x90) != 0x90) continue; + for (uint16_t *mode = video_modes; *mode != 0xFFFF; mode++) { + struct vbe_mode_info *mode_info = vbe_get_mode_info(*mode); if (mode_info->width >= highest_width && (float) mode_info->width / (float) mode_info->height < 2.0 && (mode_info->attributes & 0x1) != 0x1 && (mode_info->attributes & 0x90) != 0x90 && mode_info->memory_model != 6) { - highest = mode; + highest = *mode; highest_width = mode_info->width; + kfree(mode_info); } + kfree(mode_info); } - + kfree(video_modes); + + struct vbe_mode_info *highest_info = vbe_get_mode_info(highest); + vbe_width = highest_info->width; + vbe_height = highest_info->height; + vbe_bpp = highest_info->bpp / 8; + vbe_pitch = highest_info->pitch; + fb = (char *) highest_info->framebuffer; + uint32_t fb_psize = vbe_width * vbe_height * vbe_bpp; + for (uint32_t z = 0; z < fb_psize; z += 4096) + alloc_frame(get_page((uint32_t) (fb + z), 1, kernel_directory), 1, 1); + + serial_write("Reached set mode!\n"); vbe_set_mode(highest); } @@ -133,7 +155,7 @@ void vesa_clear() { } void vesa_set_pixel(uint16_t x, uint16_t y, uint32_t color) { - unsigned pos = x * (vbe_bpp) + y * vbe_pitch; + unsigned pos = x * vbe_bpp + y * vbe_pitch; fb[pos] = color & 255; fb[pos + 1] = (color >> 8) & 255; fb[pos + 2] = (color >> 16) & 255; @@ -169,7 +191,7 @@ void vesa_draw_rectangle(int x1, int y1, int x2, int y2, int color) { } void vesa_draw_string(char *data) { - vesa_clear(); + // vesa_clear(); // PAGE FAULT?! int i = 0; while (data[i] != '\0') { vesa_draw_char(data[i], terminal_x, terminal_y); diff --git a/src/kernel/graphics/vesa.h b/src/kernel/graphics/vesa.h index 9dbd96d..4c78219 100644 --- a/src/kernel/graphics/vesa.h +++ b/src/kernel/graphics/vesa.h @@ -56,7 +56,7 @@ struct vbe_info { * The CPUs response to the 0x4F01 call * Used to get information about a specific video mode code */ -struct vbe_mode_info { +struct vbe_mode_info_all { uint16_t attributes; uint8_t window_a; uint8_t window_b; @@ -95,6 +95,19 @@ struct vbe_mode_info { } __attribute__ ((packed)); /** + * The actual vbe mode info structure + */ +struct vbe_mode_info { + uint16_t attributes; + uint16_t pitch; + uint16_t width; + uint16_t height; + uint8_t bpp; + uint8_t memory_model; + uint32_t framebuffer; +} __attribute__ ((packed)); + +/** * Get the monitors EDID information * TODO: Add EDID/VBE resolution mode verification * @return The EDID information @@ -105,9 +118,8 @@ struct edid_data get_edid(); * Set the video mode to a specified resolution using * a video mode code * @param mode The requested video mode code from 0x4F00 call - * @return A structure with information about the video mode */ -struct vbe_mode_info *vbe_set_mode(unsigned short mode); +void vbe_set_mode(unsigned short mode); /** * Find the highest resolution using 0x4F00 and call diff --git a/src/kernel/interact.asm b/src/kernel/interact.asm index a625f8e..42b8a6b 100644 --- a/src/kernel/interact.asm +++ b/src/kernel/interact.asm @@ -44,7 +44,7 @@ section .text reloc: use32 ; by Napalm mov [REBASE(stack32_ptr)], esp ; save 32bit stack pointer sidt [REBASE(idt32_ptr)] ; save 32bit idt pointer - ;sgdt [REBASE(gdt32_ptr)] ; save 32bit gdt pointer + sgdt [REBASE(gdt32_ptr)] ; save 32bit gdt pointer lgdt [REBASE(gdt16_ptr)] ; load 16bit gdt pointer lea esi, [esp+0x24] ; set position of intnum on 32bit stack lodsd ; read intnum into eax @@ -144,8 +144,8 @@ section .text dd 0x00000000 ; table base address gdt32_ptr: ; GDT table pointer for 32bit access - dw 0x0018 ; table limit (size) - dd 0x00130000 ; table base address + dw 0x0000 ; table limit (size) + dd 0x00000000 ; table base address idt16_ptr: ; IDT table pointer for 16bit access dw 0x03FF ; table limit (size) @@ -192,4 +192,4 @@ section .text dw gdt16_ptr - gdt16_base - 1 ; table limit (size) dd gdt16_base ; table base address - int32_end: ; end marker (so we can copy the code)
\ No newline at end of file + int32_end: ; end marker (so we can copy the code) diff --git a/src/kernel/io/io.c b/src/kernel/io/io.c index 5da4e0e..e699ae0 100644 --- a/src/kernel/io/io.c +++ b/src/kernel/io/io.c @@ -3,19 +3,19 @@ #include "io.h" uint8_t receive_b(uint16_t port) { - unsigned char value; + uint8_t value; asm volatile ("inb %1, %0" : "=a"(value) : "Nd"(port)); return value; } uint16_t receive_w(uint16_t port) { - unsigned char value; - asm volatile("inb %1,%0" : "=a"(value) : "Nd"(port)); // TODO: Fix inw error + uint16_t value; + asm volatile("inw %1, %0" : "=a"(value) : "Nd"(port)); return value; } uint32_t receive_l(uint16_t port) { - unsigned char value; + uint32_t value; asm volatile ("inb %1, %0" : "=a"(value) : "Nd"(port)); return value; } diff --git a/src/kernel/kernel.c b/src/kernel/kernel.c index da0b18b..35dd4fd 100644 --- a/src/kernel/kernel.c +++ b/src/kernel/kernel.c @@ -9,22 +9,22 @@ #include "paging/kheap.h" void init() { - initialise_paging(); timer_install(); gdt_install(); + initialise_paging(); idt_install(); isrs_install(); irq_install(); init_serial(); + set_optimal_resolution(); // terminal_initialize(); // TODO: Replace VGA functions with VESA asm volatile ("sti"); } void kernel_main(void) { - set_optimal_resolution(); init(); - // vesa_draw_string("This is a testing text!"); + vesa_draw_string("This is a testing text!"); if (vesa_available) { serial_write("Loaded VESA!\n"); diff --git a/src/kernel/paging/kheap.h b/src/kernel/paging/kheap.h index a1d946c..a2254be 100644 --- a/src/kernel/paging/kheap.h +++ b/src/kernel/paging/kheap.h @@ -105,8 +105,4 @@ uint32_t kmalloc_ap(uint32_t sz, uint32_t *phys); */ uint32_t kmalloc(uint32_t sz); -/** - General deallocation function. -**/ - #endif diff --git a/src/kernel/paging/paging.c b/src/kernel/paging/paging.c index 4bb69d0..1712f7e 100644 --- a/src/kernel/paging/paging.c +++ b/src/kernel/paging/paging.c @@ -105,6 +105,18 @@ void initialise_paging() { switch_page_directory(current_directory); } +void disable_paging() { + uint32_t cr0; + asm volatile("mov %%cr0, %0": "=r"(cr0)); + cr0 &= 0x7fffffff; + asm volatile("mov %0, %%cr0"::"r"(cr0)); +} + +void enable_paging() { + switch_page_directory(kernel_directory); + switch_page_directory(current_directory); +} + void switch_page_directory(page_directory_t *dir) { current_directory = dir; asm volatile("mov %0, %%cr3"::"r"(dir->physicalAddr)); diff --git a/src/kernel/paging/paging.h b/src/kernel/paging/paging.h index 51f407f..681b84e 100644 --- a/src/kernel/paging/paging.h +++ b/src/kernel/paging/paging.h @@ -25,11 +25,21 @@ typedef struct page_directory { } page_directory_t; /** - * Initialize the environment and enables paging + * Initialize the environment and enable paging */ void initialise_paging(); /** + * Enable paging bit in CR0 (without initializing) + */ +void enable_paging(); + +/** + * Disable paging bit in CR0 + */ +void disable_paging(); + +/** * Load the page directory into the CR3 register * @param new The page directory */ |