.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
--- /dev/null
+#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);
+}
--- /dev/null
+#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;
+};
+
+}
#include "multiboot2.hpp"
#include "paging.hpp"
+#include "fb.hpp"
#include "utils.hpp"
#include "serial.hpp"
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();
}
#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