diff --git a/Kernel/Prekernel/Arch/aarch64/SerenityLogoRGB.ppm b/Kernel/Prekernel/Arch/aarch64/SerenityLogoRGB.ppm new file mode 100644 index 0000000000..6cf9490cd4 Binary files /dev/null and b/Kernel/Prekernel/Arch/aarch64/SerenityLogoRGB.ppm differ diff --git a/Kernel/Prekernel/Arch/aarch64/init.cpp b/Kernel/Prekernel/Arch/aarch64/init.cpp index d9d7f7e5ba..37d64843d8 100644 --- a/Kernel/Prekernel/Arch/aarch64/init.cpp +++ b/Kernel/Prekernel/Arch/aarch64/init.cpp @@ -7,9 +7,12 @@ #include #include +#include +#include #include #include #include +#include extern "C" [[noreturn]] void halt(); extern "C" [[noreturn]] void init(); @@ -19,6 +22,7 @@ static void set_up_el1_mode(); static void set_up_el2_mode(); static void set_up_el3_mode(); static void print_current_exception_level(const char* msg); +static void draw_logo(); static u32 query_firmware_version(); [[noreturn]] static void jump_to_os_start_from_el2(); [[noreturn]] static void jump_to_os_start_from_el3(); @@ -62,6 +66,11 @@ extern "C" [[noreturn]] void os_start() print_current_exception_level("CPU switched to:"); + auto& framebuffer = Prekernel::Framebuffer::the(); + if (framebuffer.initialized()) { + draw_logo(); + } + auto& timer = Prekernel::Timer::the(); u64 start_musec = 0; for (;;) { @@ -239,3 +248,66 @@ 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() +{ + Prekernel::BootPPMParser logo_parser(reinterpret_cast(&serenity_boot_logo_start), serenity_boot_logo_size); + if (!logo_parser.parse()) { + Prekernel::warnln("Invalid boot logo."); + return; + } + + auto& uart = Prekernel::UART::the(); + uart.print_str("Boot logo size: "); + uart.print_num(serenity_boot_logo_size); + uart.print_str("\r\n"); + uart.print_str("Width: "); + uart.print_num(logo_parser.image.width); + uart.print_str("\r\n"); + uart.print_str("Height: "); + uart.print_num(logo_parser.image.height); + uart.print_str("\r\n"); + + auto& framebuffer = Prekernel::Framebuffer::the(); + auto fb_ptr = framebuffer.gpu_buffer(); + 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 Prekernel::Framebuffer::PixelOrder::RGB: + fb_ptr[0] = logo_pixels[0]; + fb_ptr[1] = logo_pixels[1]; + fb_ptr[2] = logo_pixels[2]; + break; + case Prekernel::Framebuffer::PixelOrder::BGR: + fb_ptr[0] = logo_pixels[2]; + fb_ptr[1] = logo_pixels[1]; + fb_ptr[2] = logo_pixels[0]; + break; + default: + Prekernel::warnln("Unsupported pixel format"); + halt(); + } + + 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; + } +} diff --git a/Kernel/Prekernel/CMakeLists.txt b/Kernel/Prekernel/CMakeLists.txt index 9fde4dcb59..2119feaa07 100644 --- a/Kernel/Prekernel/CMakeLists.txt +++ b/Kernel/Prekernel/CMakeLists.txt @@ -66,6 +66,8 @@ if ("${SERENITY_ARCH}" STREQUAL "i686" OR "${SERENITY_ARCH}" STREQUAL "x86_64") endif() if ("${SERENITY_ARCH}" STREQUAL "aarch64") + embed_resource(Prekernel serenity_boot_logo "Arch/aarch64/SerenityLogoRGB.ppm") + add_custom_command( TARGET Prekernel POST_BUILD COMMAND ${CMAKE_OBJCOPY} -O binary Prekernel kernel8.img