From: Amelia Coutard Date: Thu, 5 May 2022 18:06:46 +0000 (+0200) Subject: Added a basic framebuffer X-Git-Url: https://git.ameliathe1st.gay/?a=commitdiff_plain;h=d7f5635b7cb693cca8b796fa8573b67525b8b32f;p=voyage-au-centre-des-fichiers.git Added a basic framebuffer --- diff --git a/src/boot.S b/src/boot.S index 53a9162..2be4f42 100644 --- a/src/boot.S +++ b/src/boot.S @@ -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 index 0000000..b4d6e16 --- /dev/null +++ b/src/fb.cpp @@ -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(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(&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 index 0000000..15f6e9a --- /dev/null +++ b/src/fb.hpp @@ -0,0 +1,40 @@ +#pragma once + +#include +#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 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; +}; + +} diff --git a/src/kernel.cpp b/src/kernel.cpp index f6415ae..784859f 100644 --- a/src/kernel.cpp +++ b/src/kernel.cpp @@ -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_ptrtype != 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(); } diff --git a/src/multiboot2.hpp b/src/multiboot2.hpp index 53e7135..41091ac 100644 --- a/src/multiboot2.hpp +++ b/src/multiboot2.hpp @@ -1,29 +1,96 @@ #pragma once #ifdef __cplusplus -namespace multiboot2 { -#endif +# include +# 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 next(os::phys_ptr ptr) { + return os::phys_ptr{ptr.get_phys_addr() + 8}; + } + inline os::phys_ptr next(os::phys_ptr ptr) { + return os::phys_ptr((ptr.get_phys_addr() + ptr->size + 7) / 8 * 8); // + 7) / 8 * 8 is required for alignment. + } + + uint64_t framebuffer_addr(os::phys_ptr ptr) { + return *reinterpret_cast(&ptr->rest[0]); + } + uint32_t framebuffer_pitch(os::phys_ptr ptr) { + return *reinterpret_cast(&ptr->rest[8]); + } + uint32_t framebuffer_width(os::phys_ptr ptr) { + return *reinterpret_cast(&ptr->rest[12]); + } + uint32_t framebuffer_height(os::phys_ptr ptr) { + return *reinterpret_cast(&ptr->rest[16]); + } + uint8_t framebuffer_bpp(os::phys_ptr ptr) { + return *reinterpret_cast(&ptr->rest[20]); + } + uint8_t framebuffer_type(os::phys_ptr ptr) { + return *reinterpret_cast(&ptr->rest[21]); + } + const uint8_t* color_info(os::phys_ptr ptr) { + return reinterpret_cast(&ptr->rest[24]); + } +#endif // __cplusplus + +#ifdef __cplusplus + } // namespace multiboot2 +#endif // __cplusplus