diff --git a/Kernel/Arch/aarch64/RPi/Framebuffer.cpp b/Kernel/Arch/aarch64/RPi/Framebuffer.cpp index 679725fd22..2a1f535405 100644 --- a/Kernel/Arch/aarch64/RPi/Framebuffer.cpp +++ b/Kernel/Arch/aarch64/RPi/Framebuffer.cpp @@ -5,8 +5,18 @@ */ #include +#include #include #include +#include + +extern READONLY_AFTER_INIT PhysicalAddress multiboot_framebuffer_addr; +extern READONLY_AFTER_INIT u32 multiboot_framebuffer_pitch; +extern READONLY_AFTER_INIT u32 multiboot_framebuffer_width; +extern READONLY_AFTER_INIT u32 multiboot_framebuffer_height; +extern READONLY_AFTER_INIT u8 multiboot_framebuffer_type; +extern const u32 serenity_boot_logo_start; +extern const u32 serenity_boot_logo_size; namespace Kernel::RPi { @@ -111,4 +121,69 @@ Framebuffer& Framebuffer::the() static Framebuffer instance; return instance; } + +void Framebuffer::initialize() +{ + auto& framebuffer = the(); + if (framebuffer.initialized()) { + multiboot_framebuffer_addr = PhysicalAddress((PhysicalPtr)framebuffer.gpu_buffer()); + multiboot_framebuffer_width = framebuffer.width(); + multiboot_framebuffer_height = framebuffer.height(); + multiboot_framebuffer_pitch = framebuffer.pitch(); + + VERIFY(framebuffer.pixel_order() == PixelOrder::RGB); + multiboot_framebuffer_type = MULTIBOOT_FRAMEBUFFER_TYPE_RGB; + } +} + +void Framebuffer::draw_logo(u8* framebuffer_data) +{ + BootPPMParser logo_parser(reinterpret_cast(&serenity_boot_logo_start), serenity_boot_logo_size); + if (!logo_parser.parse()) { + dbgln("Failed to parse boot logo."); + return; + } + + dbgln("Boot logo size: {} ({} x {})", serenity_boot_logo_size, logo_parser.image.width, logo_parser.image.height); + + auto fb_ptr = framebuffer_data; + auto image_left = (width() - logo_parser.image.width) / 2; + auto image_right = image_left + logo_parser.image.width; + auto image_top = (height() - logo_parser.image.height) / 2; + auto image_bottom = image_top + logo_parser.image.height; + auto logo_pixels = logo_parser.image.pixel_data; + + for (u32 y = 0; y < height(); y++) { + for (u32 x = 0; x < width(); x++) { + if (x >= image_left && x < image_right && y >= image_top && y < image_bottom) { + switch (pixel_order()) { + case RPi::Framebuffer::PixelOrder::RGB: + fb_ptr[0] = logo_pixels[0]; + fb_ptr[1] = logo_pixels[1]; + fb_ptr[2] = logo_pixels[2]; + break; + case RPi::Framebuffer::PixelOrder::BGR: + fb_ptr[0] = logo_pixels[2]; + fb_ptr[1] = logo_pixels[1]; + fb_ptr[2] = logo_pixels[0]; + break; + default: + dbgln("Unsupported pixel format"); + VERIFY_NOT_REACHED(); + } + + logo_pixels += 3; + } else { + fb_ptr[0] = 0xBD; + fb_ptr[1] = 0xBD; + fb_ptr[2] = 0xBD; + } + + fb_ptr[3] = 0xFF; + fb_ptr += 4; + } + fb_ptr += pitch() - width() * 4; + } +} + } diff --git a/Kernel/Arch/aarch64/RPi/Framebuffer.h b/Kernel/Arch/aarch64/RPi/Framebuffer.h index e14ec3c4cb..57e7dd448c 100644 --- a/Kernel/Arch/aarch64/RPi/Framebuffer.h +++ b/Kernel/Arch/aarch64/RPi/Framebuffer.h @@ -18,6 +18,7 @@ public: }; static Framebuffer& the(); + static void initialize(); bool initialized() const { return m_initialized; } u16 width() const { return m_width; } @@ -28,6 +29,8 @@ public: u32 pitch() const { return m_pitch; } PixelOrder pixel_order() { return m_pixel_order; } + void draw_logo(u8* framebuffer_data); + private: u16 m_width; u16 m_height; diff --git a/Kernel/Arch/aarch64/init.cpp b/Kernel/Arch/aarch64/init.cpp index eb84026e1d..2b29b191b1 100644 --- a/Kernel/Arch/aarch64/init.cpp +++ b/Kernel/Arch/aarch64/init.cpp @@ -47,7 +47,6 @@ READONLY_AFTER_INIT bool g_in_early_boot; namespace Kernel { -static void draw_logo(u8* framebuffer_data); static u32 query_firmware_version(); extern "C" [[noreturn]] void halt(); @@ -148,10 +147,12 @@ extern "C" [[noreturn]] void init() for (ctor_func_t* ctor = start_ctors; ctor < end_ctors; ctor++) (*ctor)(); + RPi::Framebuffer::initialize(); + auto& framebuffer = RPi::Framebuffer::the(); if (framebuffer.initialized()) { g_boot_console = &try_make_lock_ref_counted(PhysicalAddress((PhysicalPtr)framebuffer.gpu_buffer()), framebuffer.width(), framebuffer.height(), framebuffer.pitch()).value().leak_ref(); - draw_logo(static_cast(g_boot_console.load())->unsafe_framebuffer_data()); + framebuffer.draw_logo(static_cast(g_boot_console.load())->unsafe_framebuffer_data()); } initialize_interrupts(); @@ -204,58 +205,4 @@ static u32 query_firmware_version() return message_queue.query_firmware_version.version; } -extern "C" const u32 serenity_boot_logo_start; -extern "C" const u32 serenity_boot_logo_size; - -static void draw_logo(u8* framebuffer_data) -{ - BootPPMParser logo_parser(reinterpret_cast(&serenity_boot_logo_start), serenity_boot_logo_size); - if (!logo_parser.parse()) { - dbgln("Failed to parse boot logo."); - return; - } - - dbgln("Boot logo size: {} ({} x {})", serenity_boot_logo_size, logo_parser.image.width, logo_parser.image.height); - - auto& framebuffer = RPi::Framebuffer::the(); - auto fb_ptr = framebuffer_data; - auto image_left = (framebuffer.width() - logo_parser.image.width) / 2; - auto image_right = image_left + logo_parser.image.width; - auto image_top = (framebuffer.height() - logo_parser.image.height) / 2; - auto image_bottom = image_top + logo_parser.image.height; - auto logo_pixels = logo_parser.image.pixel_data; - - for (u32 y = 0; y < framebuffer.height(); y++) { - for (u32 x = 0; x < framebuffer.width(); x++) { - if (x >= image_left && x < image_right && y >= image_top && y < image_bottom) { - switch (framebuffer.pixel_order()) { - case RPi::Framebuffer::PixelOrder::RGB: - fb_ptr[0] = logo_pixels[0]; - fb_ptr[1] = logo_pixels[1]; - fb_ptr[2] = logo_pixels[2]; - break; - case RPi::Framebuffer::PixelOrder::BGR: - fb_ptr[0] = logo_pixels[2]; - fb_ptr[1] = logo_pixels[1]; - fb_ptr[2] = logo_pixels[0]; - break; - default: - dbgln("Unsupported pixel format"); - VERIFY_NOT_REACHED(); - } - - logo_pixels += 3; - } else { - fb_ptr[0] = 0xBD; - fb_ptr[1] = 0xBD; - fb_ptr[2] = 0xBD; - } - - fb_ptr[3] = 0xFF; - fb_ptr += 4; - } - fb_ptr += framebuffer.pitch() - framebuffer.width() * 4; - } -} - }