From 7843bf11d0d1d889641c1d98993fc9bc9edb363a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Lov=C3=A9n?= Date: Fri, 7 Jan 2022 00:10:25 +0100 Subject: [PATCH] Start at framebuffer drawing --- src/kernel/boot/kmain.c | 14 ++++---- src/kernel/boot/multiboot.c | 22 ++++++------- src/kernel/boot/multiboot_header.S | 9 +++++ src/kernel/drivers/framebuffer.c | 31 +++++++++++++++++ src/kernel/drivers/vga.c | 53 +++++++++++++++++++++--------- src/kernel/include/multiboot.h | 13 ++++++++ src/kernel/include/vga.h | 6 +++- 7 files changed, 112 insertions(+), 36 deletions(-) create mode 100644 src/kernel/drivers/framebuffer.c diff --git a/src/kernel/boot/kmain.c b/src/kernel/boot/kmain.c index d488afb..d53c985 100644 --- a/src/kernel/boot/kmain.c +++ b/src/kernel/boot/kmain.c @@ -20,18 +20,16 @@ registers *divbyzero(registers *r) { void kmain(uint64_t multiboot_magic, void *multiboot_data) { - vga_init(); - - debug("Started kernel\n"); - - cpu_init(); - multiboot_init(multiboot_magic, P2V(multiboot_data)); - debug_info("Kernel loaded with command line: \"%s\" by <%s>\n", kernel_boot_data.commandline, kernel_boot_data.bootloader); - + cpu_init(); memory_init(); + vga_init(); + + debug("Started kernel\n"); + debug_info("Kernel loaded with command line: \"%s\" by <%s>\n", kernel_boot_data.commandline, kernel_boot_data.bootloader); + bind_interrupt(0, divbyzero); // Force a divide by zero error diff --git a/src/kernel/boot/multiboot.c b/src/kernel/boot/multiboot.c index c3414ef..1f56987 100644 --- a/src/kernel/boot/multiboot.c +++ b/src/kernel/boot/multiboot.c @@ -29,17 +29,6 @@ struct mmap { struct mmap_entry entries[]; }__attribute__((packed)); -struct fbinfo { - uint64_t framebuffer_addr; - uint32_t framebuffer_pitch; - uint32_t framebuffer_width; - uint32_t framebuffer_height; - uint8_t framebuffer_bpp; - uint8_t framebuffer_type; - uint8_t reserved; - uint8_t data[]; -}__attribute__((packed)); - static int parse_multiboot2(struct taglist *tags) { struct mmap *mmap; @@ -60,7 +49,8 @@ static int parse_multiboot2(struct taglist *tags) kernel_boot_data.mmap_len = (tag->size - 8)/mmap->entry_size; kernel_boot_data.mmap_size = (tag->size - 8); break; - case 8: + case MBOOT2_TAG_FBINFO: + kernel_boot_data.fbinfo = (void *)tag->data; break; } @@ -101,10 +91,18 @@ int multiboot_get_memory_area(size_t index, uintptr_t *start, uintptr_t *end, ui int multiboot_page_used(uintptr_t page) { #define within_page(st, l) (((uintptr_t)st + l) > page && (uintptr_t)st < (page + PAGE_SIZE)) + + size_t fb_size = 0; + uintptr_t fb_start = 0; + if(kernel_boot_data.fbinfo) { + fb_start = kernel_boot_data.fbinfo->framebuffer_addr; + fb_size = kernel_boot_data.fbinfo->framebuffer_pitch*(kernel_boot_data.fbinfo->framebuffer_height + 1); + } if( within_page(kernel_boot_data.bootloader, strlen(kernel_boot_data.bootloader)) || within_page(kernel_boot_data.commandline, strlen(kernel_boot_data.commandline)) || within_page(kernel_boot_data.mmap, kernel_boot_data.mmap_size) || + within_page(fb_start, fb_size) || 0) { debug("Page %x used\n", page); return 1; diff --git a/src/kernel/boot/multiboot_header.S b/src/kernel/boot/multiboot_header.S index 3d5ee9b..db382fe 100644 --- a/src/kernel/boot/multiboot_header.S +++ b/src/kernel/boot/multiboot_header.S @@ -10,6 +10,15 @@ Multiboot2Header: //; Multiboot tag list +.short 5 //; Request graphics mode +.short 0 +.long 20 +.long 0 +.long 0 +.long 0 + +.long 0 //; Pad to multiple of 8 bytes + .short 0 //; End tag .short 0 .long 8 diff --git a/src/kernel/drivers/framebuffer.c b/src/kernel/drivers/framebuffer.c new file mode 100644 index 0000000..b2a26d5 --- /dev/null +++ b/src/kernel/drivers/framebuffer.c @@ -0,0 +1,31 @@ +#include +#include +#include + +void framebuffer_init(struct fbinfo *fbinfo) +{ + size_t fb_size = fbinfo->framebuffer_pitch * (fbinfo->framebuffer_height+1); + uintptr_t fb_end = fbinfo->framebuffer_addr + fb_size; + + for(uintptr_t p = fbinfo->framebuffer_addr; p < fb_end; p += PAGE_SIZE) + { + vmm_set_page(kernel_P4, (uint64_t)P2V(p), p, PAGE_WRITE | PAGE_PRESENT); + } + + uint8_t *fb = P2V(fbinfo->framebuffer_addr); + + for(uint32_t y = 0; y < 1; y++) + { + for(uint32_t x = 0; x < fbinfo->framebuffer_width; x++) + { + unsigned int bpp = fbinfo->framebuffer_bpp/8; + unsigned int loc = \ + y*fbinfo->framebuffer_pitch + \ + x*(bpp); + fb[loc++] = 0xFF; + fb[loc++] = 0; + fb[loc] = 0xFF; + } + } + +} \ No newline at end of file diff --git a/src/kernel/drivers/vga.c b/src/kernel/drivers/vga.c index dd4ac38..e6bd6a5 100644 --- a/src/kernel/drivers/vga.c +++ b/src/kernel/drivers/vga.c @@ -1,6 +1,9 @@ #include #include #include +#include +#include +#include #define VGA_COLS 80 #define VGA_ROWS 24 @@ -26,15 +29,29 @@ struct vga_cell buffer[VGA_SIZE]; uint64_t cursor; uint8_t format; +static int vga_setup = 0; +static int vga_type; + void vga_init() { - vidmem = VGA_MEMORY; - memset(vidmem, 0, VGA_SIZE*sizeof(struct vga_cell)); + struct fbinfo *fbinfo = kernel_boot_data.fbinfo; + vga_type = fbinfo->framebuffer_type; + switch(vga_type) + { + case 1: + framebuffer_init(fbinfo); + break; + case 2: + vidmem = VGA_MEMORY; + memset(vidmem, 0, VGA_SIZE*sizeof(struct vga_cell)); + format = 0x07; + break; + } - format = 0x07; + vga_setup = 1; } -void movecursor() +static void movecursor() { outb(VGA_ADDRESS_PORT, VGA_REGISTER_CURSOR_POS_LOW); outb(VGA_DATA_PORT, (uint8_t)(cursor & 0xFF)); @@ -42,12 +59,13 @@ void movecursor() outb(VGA_DATA_PORT, (uint8_t)((cursor >> 8) & 0xFF)); } -void flush() +static void flush() { - memcpy(vidmem, buffer, sizeof(buffer)); + if(vga_setup) + memcpy(vidmem, buffer, sizeof(buffer)); } -void scroll() +static void scroll() { while(cursor >= VGA_SIZE) { @@ -59,15 +77,20 @@ void scroll() void vga_write(char c) { - switch(c) + switch(vga_type) { - case '\n': - cursor += VGA_COLS - VGA_COL(cursor); + case 2: + switch(c) + { + case '\n': + cursor += VGA_COLS - VGA_COL(cursor); + break; + default: + buffer[cursor++] = (struct vga_cell){.c = c, .f = format}; + } + scroll(); + flush(); + movecursor(); break; - default: - buffer[cursor++] = (struct vga_cell){.c = c, .f = format}; } - scroll(); - flush(); - movecursor(); } \ No newline at end of file diff --git a/src/kernel/include/multiboot.h b/src/kernel/include/multiboot.h index 30d0e94..c2c4b2b 100644 --- a/src/kernel/include/multiboot.h +++ b/src/kernel/include/multiboot.h @@ -13,6 +13,18 @@ #ifndef __ASSEMBLER__ #include + +struct fbinfo { + uint64_t framebuffer_addr; + uint32_t framebuffer_pitch; + uint32_t framebuffer_width; + uint32_t framebuffer_height; + uint8_t framebuffer_bpp; + uint8_t framebuffer_type; + uint8_t reserved; + uint8_t color_info[]; +}__attribute__((packed)); + struct kernel_boot_data_st{ int multiboot_version; char *bootloader; @@ -20,6 +32,7 @@ struct kernel_boot_data_st{ size_t mmap_size; unsigned int mmap_len; void *mmap; + struct fbinfo *fbinfo; }; #define MMAP_FREE 1 diff --git a/src/kernel/include/vga.h b/src/kernel/include/vga.h index eab39d6..6e16caf 100644 --- a/src/kernel/include/vga.h +++ b/src/kernel/include/vga.h @@ -1,8 +1,12 @@ #pragma once #include +#include #define VGA_MEMORY P2V(0xB8000) // drivers/vga.c void vga_init(); -void vga_write(char c); \ No newline at end of file +void vga_write(char c); + +// drivers/framebuffer.c +void framebuffer_init(struct fbinfo *fbinfo); \ No newline at end of file