]> git.ameliathe1st.gay Git - voyage-au-centre-des-fichiers.git/commitdiff
Added a basic framebuffer
authorAmelia Coutard <eliottulio.coutard@gmail.com>
Thu, 5 May 2022 18:06:46 +0000 (20:06 +0200)
committerAmelia Coutard <eliottulio.coutard@gmail.com>
Thu, 5 May 2022 18:07:14 +0000 (20:07 +0200)
src/boot.S
src/fb.cpp [new file with mode: 0644]
src/fb.hpp [new file with mode: 0644]
src/kernel.cpp
src/multiboot2.hpp

index 53a9162ff96e021c95acb9e0b8fea453e1f60ad7..2be4f42325942fceb7937825bb9608f6a440b2ec 100644 (file)
@@ -9,6 +9,14 @@ multiboot_header_start:
        .int multiboot2_arch_i386_32bit
        .int multiboot_header_end - multiboot_header_start
        .int multiboot2_checksum(multiboot2_arch_i386_32bit, multiboot_header_end - multiboot_header_start)
+       /* Framebuffer tag: */
+       .align 8
+       .short 5
+       .short 0
+       .int 20
+       .int 0
+       .int 0
+       .int 32
        /* End tag: */
        .align 8
        .short 0
diff --git a/src/fb.cpp b/src/fb.cpp
new file mode 100644 (file)
index 0000000..b4d6e16
--- /dev/null
@@ -0,0 +1,53 @@
+#include "serial.hpp"
+#include "fb.hpp"
+
+os::color os::operator*(color c1, color c2) {
+       return {
+               .r = uint8_t(int(c1.r) * int(c2.r) / 256),
+               .g = uint8_t(int(c1.g) * int(c2.g) / 256),
+               .b = uint8_t(int(c1.b) * int(c2.b) / 256),
+       };
+}
+
+os::framebuffer::framebuffer(uint64_t addr, uint32_t pitch, uint32_t width, uint32_t height, uint8_t bpp, uint8_t type, const uint8_t* color_info) {
+       address = phys_ptr<volatile uint8_t>(addr);
+       this->pitch = pitch;
+       this->width = width;
+       this->height = height;
+       this->bpp = bpp;
+       if (type != 1) {
+               os::println("Error: framebuffer not in direct RGB mode.");
+               os::halt();
+       }
+       if (bpp != 32) {
+               os::println("Error: framebuffer bpp != 32.");
+               os::halt();
+       }
+
+       r_pos =  color_info[0];
+       r_mask = (1 << color_info[1]) - 1;
+       g_pos =  color_info[2];
+       g_mask = (1 << color_info[3]) - 1;
+       b_pos =  color_info[4];
+       b_mask = (1 << color_info[5]) - 1;
+}
+void os::framebuffer::putpixel(size_t x, size_t y, color c) {
+       *reinterpret_cast<volatile uint32_t*>(&address[pitch * y + x * bpp / 8]) = color_to_data(c);
+}
+void os::framebuffer::clear(color c) {
+       for (size_t x = 0; x < width; x++) {
+               for (size_t y = 0; y < height; y++) {
+                       putpixel(x, y, c);
+               }
+       }
+}
+size_t os::framebuffer::get_width() const {
+       return width;
+}
+size_t os::framebuffer::get_height() const {
+       return height;
+}
+
+uint32_t os::framebuffer::color_to_data(color c) const {
+return ((uint32_t(c.r) & r_mask) << r_pos) | ((uint32_t(c.g) & g_mask) << g_pos) | ((uint32_t(c.b) & b_mask) << b_pos);
+}
diff --git a/src/fb.hpp b/src/fb.hpp
new file mode 100644 (file)
index 0000000..15f6e9a
--- /dev/null
@@ -0,0 +1,40 @@
+#pragma once
+
+#include <stdint.h>
+#include "utils.hpp"
+
+namespace os {
+
+struct color {
+       uint8_t r;
+       uint8_t g;
+       uint8_t b;
+};
+color operator*(color c1, color c2);
+
+class framebuffer {
+public:
+       framebuffer() = default;
+       framebuffer(uint64_t addr, uint32_t pitch, uint32_t width, uint32_t height, uint8_t bpp, uint8_t type, const uint8_t* color_info);
+       void putpixel(size_t x, size_t y, color c);
+       void clear(color c);
+       size_t get_width() const;
+       size_t get_height() const;
+
+private:
+       uint32_t color_to_data(color c) const;
+
+       phys_ptr<volatile uint8_t> address = nullptr;
+       size_t pitch;
+       size_t width;
+       size_t height;
+       uint8_t bpp;
+       uint8_t r_pos;
+       uint8_t r_mask;
+       uint8_t g_pos;
+       uint8_t g_mask;
+       uint8_t b_pos;
+       uint8_t b_mask;
+};
+
+}
index f6415ae3bd2f0b956e18650818316c71cddf22da..784859fc919692f75d502c16f38d260f5dbe7601 100644 (file)
@@ -1,5 +1,6 @@
 #include "multiboot2.hpp"
 #include "paging.hpp"
+#include "fb.hpp"
 #include "utils.hpp"
 #include "serial.hpp"
 
@@ -14,11 +15,34 @@ extern "C" void kmain(unsigned long magic, os::phys_ptr<const multiboot2::info_s
        asm("mov $test_ram - 0xFFFFFFFF80000000,%0" : "=ri"(ram_ptr));
        os::paging::page_allocator page_allocator(ram_ptr);
 
+       os::framebuffer framebuffer;
+
        for (auto it = multiboot2::next(info); it->type != multiboot2::info::type_t::end; it = multiboot2::next(it)) {
                switch (it->type) {
+               case multiboot2::info::type_t::framebuffer_info:
+                       framebuffer = os::framebuffer(
+                               multiboot2::framebuffer_addr(it),
+                               multiboot2::framebuffer_pitch(it),
+                               multiboot2::framebuffer_width(it),
+                               multiboot2::framebuffer_height(it),
+                               multiboot2::framebuffer_bpp(it),
+                               multiboot2::framebuffer_type(it),
+                               multiboot2::color_info(it)
+                       );
+                       break;
                default: break;
                }
        }
 
+       for (size_t x = 0; x < framebuffer.get_width(); x++) {
+               for (size_t y = 0; y < framebuffer.get_height(); y++) {
+                       framebuffer.putpixel(x, y, {
+                               .r = uint8_t(x * 256 / framebuffer.get_width()),
+                               .g = 0,
+                               .b = uint8_t(y * 256 / framebuffer.get_height()),
+                       });
+               }
+       }
+
        os::halt();
 }
index 53e71354fd99075bf7c25699382bdb567e4157b3..41091acd0647518485a7b1fcaf7a0aa1c5bf6a0d 100644 (file)
@@ -1,29 +1,96 @@
 #pragma once
 
 #ifdef __cplusplus
-namespace multiboot2 {
-#endif
+#      include <stdint.h>
+#      include "utils.hpp"
+       namespace multiboot2 {
+#endif // __cplusplus
 
 #ifdef __cplusplus
-       constexpr unsigned int magic = 0xE85250D6;
+       constexpr uint32_t magic = 0xE85250D6;
 #else
 #      define multiboot2_magic 0xE85250D6
-#endif
+#endif // __cplusplus
 
 #ifdef __cplusplus
-       constexpr unsigned int arch_i386_32bit = 0;
-       constexpr unsigned int arch_mips_32bit = 4;
+       constexpr uint32_t arch_i386_32bit = 0;
+       constexpr uint32_t arch_mips_32bit = 4;
 #else
 #      define multiboot2_arch_i386_32bit 0
 #      define multiboot2_arch_mips_32bit 4
-#endif
+#endif // __cplusplus
 
 #ifdef __cplusplus
-       constexpr unsigned int checksum(unsigned int arch, unsigned int length) { return -(magic + arch + length); }
+       constexpr uint32_t checksum(uint32_t arch, uint32_t length) { return -(magic + arch + length); }
 #else
 #      define multiboot2_checksum(arch, length) -(multiboot2_magic + (arch) + (length))
-#endif
+#endif // __cplusplus
 
 #ifdef __cplusplus
-}
-#endif
+       struct __attribute__((packed)) info_start {
+               uint32_t total_size;
+               uint32_t reserved;
+       };
+       struct __attribute__((packed)) info {
+               enum class type_t : uint32_t {
+                       end = 0,
+                       basic_memory_info = 4,
+                       bios_boot_device = 5,
+                       boot_command_line = 1,
+                       modules = 3,
+                       elf_symbols = 9,
+                       memory_map = 6,
+                       boot_loader_name = 2,
+                       apm_table = 10,
+                       vbe_info = 7,
+                       framebuffer_info = 8,
+                       efi_32bit_system_table_pointer = 11,
+                       efi_64bit_system_table_pointer = 12,
+                       smbios_tables = 13,
+                       acpi_old_rsdp = 14,
+                       acpi_new_rsdp = 15,
+                       networking_info = 16,
+                       efi_memory_map = 17,
+                       efi_boot_services_not_terminated = 18,
+                       efi_32bit_image_handle_pointer = 19,
+                       efi_64bit_image_handle_pointer = 20,
+                       image_load_base_physical_address = 21,
+               };
+               type_t type;
+               uint32_t size;
+               uint8_t rest[];
+       };
+
+       inline os::phys_ptr<const info> next(os::phys_ptr<const info_start> ptr) {
+               return os::phys_ptr<const info>{ptr.get_phys_addr() + 8};
+       }
+       inline os::phys_ptr<const info> next(os::phys_ptr<const info> ptr) {
+               return os::phys_ptr<const info>((ptr.get_phys_addr() + ptr->size + 7) / 8 * 8); // + 7) / 8 * 8 is required for alignment.
+       }
+
+       uint64_t framebuffer_addr(os::phys_ptr<const info> ptr) {
+               return *reinterpret_cast<const uint64_t*>(&ptr->rest[0]);
+       }
+       uint32_t framebuffer_pitch(os::phys_ptr<const info> ptr) {
+               return *reinterpret_cast<const uint32_t*>(&ptr->rest[8]);
+       }
+       uint32_t framebuffer_width(os::phys_ptr<const info> ptr) {
+               return *reinterpret_cast<const uint32_t*>(&ptr->rest[12]);
+       }
+       uint32_t framebuffer_height(os::phys_ptr<const info> ptr) {
+               return *reinterpret_cast<const uint32_t*>(&ptr->rest[16]);
+       }
+       uint8_t framebuffer_bpp(os::phys_ptr<const info> ptr) {
+               return *reinterpret_cast<const uint8_t*>(&ptr->rest[20]);
+       }
+       uint8_t framebuffer_type(os::phys_ptr<const info> ptr) {
+               return *reinterpret_cast<const uint8_t*>(&ptr->rest[21]);
+       }
+       const uint8_t* color_info(os::phys_ptr<const info> ptr) {
+               return reinterpret_cast<const uint8_t*>(&ptr->rest[24]);
+       }
+#endif // __cplusplus
+
+#ifdef __cplusplus
+       } // namespace multiboot2
+#endif // __cplusplus