:: commit 6f15587c85599264239fa7a02813b40f4a8e1dd4

Andy-Python-Programmer <andypythonappdeveloper@gmail.com> — 2021-09-10 08:41

parents: 6d034adc5a

multiboot2: add the framebuffer tag

Signed-off-by: Andy-Python-Programmer <andypythonappdeveloper@gmail.com>
diff --git a/stage23/protos/multiboot2.c b/stage23/protos/multiboot2.c
index e070ee37..06759d1a 100644
--- a/stage23/protos/multiboot2.c
+++ b/stage23/protos/multiboot2.c
@@ -14,6 +14,7 @@
 #include <fs/file.h>
 #include <mm/vmm.h>
 #include <mm/pmm.h>
+#include <drivers/vga_textmode.h>
 
 static uint8_t* multiboot2_info_buffer = NULL;
 static uint32_t multiboot2_info_size = 0;
@@ -124,12 +125,46 @@ void multiboot2_load(char *config, char* cmdline) {
 
     print("multiboot2: found kernel entry point at: %x\n", entry_point);
     
+    struct multiboot_header_tag_framebuffer *fbtag = NULL;
+
     // Iterate through the entries...
     for (struct multiboot_header_tag* tag = (struct multiboot_header_tag*)(header + 1);
          tag < (struct multiboot_header_tag*)((uintptr_t)header + header->header_length) && tag->type != MULTIBOOT_HEADER_TAG_END;
          tag = (struct multiboot_header_tag*)((uintptr_t)tag + ALIGN_UP(tag->size, MULTIBOOT_TAG_ALIGN))) {
   
         switch (tag->type) {
+            case MULTIBOOT_HEADER_TAG_INFORMATION_REQUEST: {
+                // Iterate the requests and check if they are supported by or not.
+                struct multiboot_header_tag_information_request* request = (void*)tag;
+                uint32_t size = (request->size - sizeof(struct multiboot_header_tag_information_request)) 
+                    / sizeof(uint32_t);
+                    
+                for (uint32_t i = 0; i < size; i++) {
+                    uint32_t r = request->requests[i];
+
+                    switch(r) {
+                        // We already support the following requests:
+                        case MULTIBOOT_TAG_TYPE_CMDLINE:
+                        case MULTIBOOT_TAG_TYPE_BOOT_LOADER_NAME:
+                        case MULTIBOOT_TAG_TYPE_MODULE:
+                        case MULTIBOOT_TAG_TYPE_MMAP:
+                        case MULTIBOOT_TAG_TYPE_EFI_MMAP:
+                        case MULTIBOOT_TAG_TYPE_FRAMEBUFFER:
+                        case MULTIBOOT_TAG_TYPE_ELF_SECTIONS:
+                            break;
+
+                        default: {
+                            if (!(request->flags & MULTIBOOT_HEADER_TAG_OPTIONAL))
+                                panic("multiboot2: requested tag `%d` which is not supported", r);
+                        } break;
+                    }
+                }
+            } break;
+
+            case MULTIBOOT_HEADER_TAG_FRAMEBUFFER: {
+                fbtag = (struct multiboot_header_tag_framebuffer*)tag;
+            } break;
+
             default: panic("multiboot2: unknown tag type");
         }
     }
@@ -168,6 +203,52 @@ void multiboot2_load(char *config, char* cmdline) {
     // Create framebuffer tag
     //////////////////////////////////////////////
     {
+        if (fbtag) {
+            size_t req_width = fbtag->width;
+            size_t req_height = fbtag->height;
+            size_t req_bpp = 0x00;
+            
+            char *resolution = config_get_value(config, 0, "RESOLUTION");
+            if (resolution != NULL)
+                parse_resolution(&req_width, &req_height, &req_bpp, resolution);
+            
+            struct fb_info fbinfo;
+            if (!fb_init(&fbinfo, req_width, req_height, req_bpp))
+                panic("stivale: Unable to set video mode");
+
+            memmap_alloc_range(fbinfo.framebuffer_addr,
+                            (uint64_t)fbinfo.framebuffer_pitch * fbinfo.framebuffer_height,
+                            MEMMAP_FRAMEBUFFER, false, false, false, true);
+
+            struct multiboot_tag_framebuffer framebuffer = {
+                .common = {
+                    .type = MULTIBOOT_TAG_TYPE_FRAMEBUFFER,
+                    .size = sizeof(struct multiboot_tag_framebuffer),
+                    .framebuffer_addr = fbinfo.framebuffer_addr,
+                    .framebuffer_pitch = fbinfo.framebuffer_pitch,
+                    .framebuffer_width = fbinfo.framebuffer_width,
+                    .framebuffer_height = fbinfo.framebuffer_height,
+                    .framebuffer_bpp = fbinfo.framebuffer_bpp,
+                    .framebuffer_type = MULTIBOOT_FRAMEBUFFER_TYPE_RGB // We only support RGB for VBE
+                },
+
+                .framebuffer_red_field_position = fbinfo.red_mask_shift,
+                .framebuffer_red_mask_size = fbinfo.red_mask_size,
+                .framebuffer_green_field_position = fbinfo.green_mask_shift,
+                .framebuffer_green_mask_size = fbinfo.green_mask_size,
+                .framebuffer_blue_field_position = fbinfo.blue_mask_shift,
+                .framebuffer_blue_mask_size = fbinfo.blue_mask_size,
+            };
+
+            push_boot_param(&framebuffer, sizeof(struct multiboot_tag_elf_sections));
+        } else {
+#if uefi == 1
+            panic("multiboot2: Cannot use text mode with UEFI.");
+#elif bios == 1
+            size_t rows, cols;
+            init_vga_textmode(&rows, &cols, false);
+#endif
+        }
     }
 
     //////////////////////////////////////////////
tab: 248 wrap: offon