17db9fbfeSFrançois Revol /* 27db9fbfeSFrançois Revol * Copyright 2004-2009, Axel Dörfler, axeld@pinc-software.de. 37db9fbfeSFrançois Revol * Copyright 2008, Stephan Aßmus <superstippi@gmx.de> 47db9fbfeSFrançois Revol * Copyright 2008, Philippe Saint-Pierre <stpere@gmail.com> 57db9fbfeSFrançois Revol * Distributed under the terms of the MIT License. 67db9fbfeSFrançois Revol */ 77db9fbfeSFrançois Revol 87db9fbfeSFrançois Revol 97db9fbfeSFrançois Revol #include <arch/cpu.h> 107db9fbfeSFrançois Revol #include <boot/stage2.h> 117db9fbfeSFrançois Revol #include <boot/platform.h> 127db9fbfeSFrançois Revol #include <boot/menu.h> 137db9fbfeSFrançois Revol #include <boot/kernel_args.h> 147db9fbfeSFrançois Revol #include <boot/platform/generic/video.h> 1589fa2a85SPhilippe Houdoin #include <boot/images.h> 167db9fbfeSFrançois Revol 177db9fbfeSFrançois Revol #include <stdio.h> 187db9fbfeSFrançois Revol #include <stdlib.h> 197db9fbfeSFrançois Revol 2067938b0dSPhilippe Houdoin #include <zlib.h> 2167938b0dSPhilippe Houdoin 227db9fbfeSFrançois Revol 237db9fbfeSFrançois Revol //#define TRACE_VIDEO 247db9fbfeSFrançois Revol #ifdef TRACE_VIDEO 257db9fbfeSFrançois Revol # define TRACE(x) dprintf x 267db9fbfeSFrançois Revol #else 277db9fbfeSFrançois Revol # define TRACE(x) ; 287db9fbfeSFrançois Revol #endif 297db9fbfeSFrançois Revol 307db9fbfeSFrançois Revol 3167938b0dSPhilippe Houdoin static status_t 3267938b0dSPhilippe Houdoin uncompress(const uint8 compressed[], unsigned int compressedSize, 3367938b0dSPhilippe Houdoin uint8* uncompressed, unsigned int uncompressedSize) 3467938b0dSPhilippe Houdoin { 3567938b0dSPhilippe Houdoin if (compressedSize == 0 || uncompressedSize == 0) 3667938b0dSPhilippe Houdoin return B_BAD_VALUE; 3767938b0dSPhilippe Houdoin 3867938b0dSPhilippe Houdoin // prepare zlib stream 3967938b0dSPhilippe Houdoin z_stream zStream = { 4067938b0dSPhilippe Houdoin (Bytef*)compressed, // next_in 4167938b0dSPhilippe Houdoin compressedSize, // avail_in 4267938b0dSPhilippe Houdoin 0, // total_in 4367938b0dSPhilippe Houdoin (Bytef*)uncompressed, // next_out 4467938b0dSPhilippe Houdoin uncompressedSize, // avail_out 4567938b0dSPhilippe Houdoin 0, // total_out 4667938b0dSPhilippe Houdoin 0, // msg 4767938b0dSPhilippe Houdoin 0, // state 4867938b0dSPhilippe Houdoin Z_NULL, // zalloc (kernel_args_malloc?) 4967938b0dSPhilippe Houdoin Z_NULL, // zfree (kernel_args_free?) 5067938b0dSPhilippe Houdoin Z_NULL, // opaque 5167938b0dSPhilippe Houdoin 0, // data_type 5267938b0dSPhilippe Houdoin 0, // adler 5367938b0dSPhilippe Houdoin 0 // reserved 5467938b0dSPhilippe Houdoin }; 5567938b0dSPhilippe Houdoin 5667938b0dSPhilippe Houdoin int zlibError = inflateInit(&zStream); 5767938b0dSPhilippe Houdoin if (zlibError != Z_OK) 5867938b0dSPhilippe Houdoin return B_ERROR; // TODO: translate zlibError 5967938b0dSPhilippe Houdoin 6067938b0dSPhilippe Houdoin // inflate 6167938b0dSPhilippe Houdoin status_t status = B_OK; 6267938b0dSPhilippe Houdoin zlibError = inflate(&zStream, Z_FINISH); 6367938b0dSPhilippe Houdoin if (zlibError != Z_STREAM_END) { 6467938b0dSPhilippe Houdoin if (zlibError == Z_OK) 6567938b0dSPhilippe Houdoin status = B_BUFFER_OVERFLOW; 6667938b0dSPhilippe Houdoin else 6767938b0dSPhilippe Houdoin status = B_ERROR; // TODO: translate zlibError 6867938b0dSPhilippe Houdoin } 6967938b0dSPhilippe Houdoin 7067938b0dSPhilippe Houdoin // clean up 7167938b0dSPhilippe Houdoin zlibError = inflateEnd(&zStream); 7267938b0dSPhilippe Houdoin if (zlibError != Z_OK && status == B_OK) 7367938b0dSPhilippe Houdoin status = B_ERROR; // TODO: translate zlibError 7467938b0dSPhilippe Houdoin 7567938b0dSPhilippe Houdoin if (status == B_OK && zStream.total_out != uncompressedSize) 7667938b0dSPhilippe Houdoin status = B_ERROR; 7767938b0dSPhilippe Houdoin 7867938b0dSPhilippe Houdoin return status; 7967938b0dSPhilippe Houdoin } 8067938b0dSPhilippe Houdoin 8167938b0dSPhilippe Houdoin 827db9fbfeSFrançois Revol extern "C" status_t 8304cbc258SFredrik Holmqvist video_display_splash(addr_t frameBuffer) 847db9fbfeSFrançois Revol { 857db9fbfeSFrançois Revol if (!gKernelArgs.frame_buffer.enabled) 867db9fbfeSFrançois Revol return B_NO_INIT; 877db9fbfeSFrançois Revol 8804cbc258SFredrik Holmqvist addr_t pos = 0; 8904cbc258SFredrik Holmqvist // Limit area to clear to estimated screen area 9004cbc258SFredrik Holmqvist // UEFI can happily report a >256M framebuffer 9104cbc258SFredrik Holmqvist addr_t size = min_c(gKernelArgs.frame_buffer.width 92*1368eabbSFredrik Holmqvist * gKernelArgs.frame_buffer.height * 4u, 937db9fbfeSFrançois Revol gKernelArgs.frame_buffer.physical_buffer.size); 947db9fbfeSFrançois Revol 9504cbc258SFredrik Holmqvist if (size >= 64) { 9604cbc258SFredrik Holmqvist // Align writes 97*1368eabbSFredrik Holmqvist for (addr_t align = (8 - (frameBuffer & 7)) & 7; pos < align; pos++) 9804cbc258SFredrik Holmqvist *(char*)(frameBuffer + pos) = 0; 9904cbc258SFredrik Holmqvist // Write eight bytes, many many times, but not too many 10004cbc258SFredrik Holmqvist for (addr_t alignSize = size - 8; pos < alignSize; pos +=8) { 10104cbc258SFredrik Holmqvist *(uint32*)(frameBuffer + pos) = 0; 10204cbc258SFredrik Holmqvist *(uint32*)(frameBuffer + pos + 4) = 0; 10304cbc258SFredrik Holmqvist } 10404cbc258SFredrik Holmqvist } 10504cbc258SFredrik Holmqvist // Write a few bytes more 10604cbc258SFredrik Holmqvist for (; pos < size; pos++) 10704cbc258SFredrik Holmqvist *(char*)(frameBuffer + pos) = 0; 10804cbc258SFredrik Holmqvist 1097db9fbfeSFrançois Revol uint8* uncompressedLogo = NULL; 11067938b0dSPhilippe Houdoin unsigned int uncompressedSize = kSplashLogoWidth * kSplashLogoHeight; 1117db9fbfeSFrançois Revol switch (gKernelArgs.frame_buffer.depth) { 1127db9fbfeSFrançois Revol case 8: 1137db9fbfeSFrançois Revol platform_set_palette(k8BitPalette); 11467938b0dSPhilippe Houdoin uncompressedLogo = (uint8*)kernel_args_malloc(uncompressedSize); 1157db9fbfeSFrançois Revol if (uncompressedLogo == NULL) 1167db9fbfeSFrançois Revol return B_NO_MEMORY; 11767938b0dSPhilippe Houdoin 11867938b0dSPhilippe Houdoin uncompress(kSplashLogo8BitCompressedImage, 11967938b0dSPhilippe Houdoin sizeof(kSplashLogo8BitCompressedImage), uncompressedLogo, 12067938b0dSPhilippe Houdoin uncompressedSize); 1217db9fbfeSFrançois Revol break; 12267938b0dSPhilippe Houdoin default: // 24 bits is assumed here 12367938b0dSPhilippe Houdoin uncompressedSize *= 3; 12467938b0dSPhilippe Houdoin uncompressedLogo = (uint8*)kernel_args_malloc(uncompressedSize); 1257db9fbfeSFrançois Revol if (uncompressedLogo == NULL) 1267db9fbfeSFrançois Revol return B_NO_MEMORY; 12767938b0dSPhilippe Houdoin 12867938b0dSPhilippe Houdoin uncompress(kSplashLogo24BitCompressedImage, 12967938b0dSPhilippe Houdoin sizeof(kSplashLogo24BitCompressedImage), uncompressedLogo, 13067938b0dSPhilippe Houdoin uncompressedSize); 1317db9fbfeSFrançois Revol break; 1327db9fbfeSFrançois Revol } 1337db9fbfeSFrançois Revol 1347db9fbfeSFrançois Revol // TODO: support 4-bit indexed version of the images! 1357db9fbfeSFrançois Revol 1367db9fbfeSFrançois Revol // render splash logo 1377db9fbfeSFrançois Revol uint16 iconsHalfHeight = kSplashIconsHeight / 2; 1387db9fbfeSFrançois Revol 1397db9fbfeSFrançois Revol int width = min_c(kSplashLogoWidth, gKernelArgs.frame_buffer.width); 1407db9fbfeSFrançois Revol int height = min_c(kSplashLogoHeight + iconsHalfHeight, 1417db9fbfeSFrançois Revol gKernelArgs.frame_buffer.height); 1427db9fbfeSFrançois Revol int placementX = max_c(0, min_c(100, kSplashLogoPlacementX)); 1437db9fbfeSFrançois Revol int placementY = max_c(0, min_c(100, kSplashLogoPlacementY)); 1447db9fbfeSFrançois Revol 1457db9fbfeSFrançois Revol int x = (gKernelArgs.frame_buffer.width - width) * placementX / 100; 1467db9fbfeSFrançois Revol int y = (gKernelArgs.frame_buffer.height - height) * placementY / 100; 1477db9fbfeSFrançois Revol 1487db9fbfeSFrançois Revol height = min_c(kSplashLogoHeight, gKernelArgs.frame_buffer.height); 1497db9fbfeSFrançois Revol switch (gKernelArgs.frame_buffer.depth) { 1507db9fbfeSFrançois Revol case 8: 1517db9fbfeSFrançois Revol break; 1527db9fbfeSFrançois Revol } 1537db9fbfeSFrançois Revol video_blit_image(frameBuffer, uncompressedLogo, width, height, 1547db9fbfeSFrançois Revol kSplashLogoWidth, x, y); 1557db9fbfeSFrançois Revol 1567db9fbfeSFrançois Revol kernel_args_free(uncompressedLogo); 1577db9fbfeSFrançois Revol 1587db9fbfeSFrançois Revol const uint8* lowerHalfIconImage; 15967938b0dSPhilippe Houdoin uncompressedSize = kSplashIconsWidth * kSplashIconsHeight; 1607db9fbfeSFrançois Revol switch (gKernelArgs.frame_buffer.depth) { 1617db9fbfeSFrançois Revol case 8: 1627db9fbfeSFrançois Revol // pointer into the lower half of the icons image data 1637db9fbfeSFrançois Revol gKernelArgs.boot_splash 16467938b0dSPhilippe Houdoin = (uint8*)kernel_args_malloc(uncompressedSize); 16562d36f98SAlex Smith if (gKernelArgs.boot_splash == NULL) 1667db9fbfeSFrançois Revol return B_NO_MEMORY; 16767938b0dSPhilippe Houdoin uncompress(kSplashIcons8BitCompressedImage, 16867938b0dSPhilippe Houdoin sizeof(kSplashIcons8BitCompressedImage), 16967938b0dSPhilippe Houdoin gKernelArgs.boot_splash, uncompressedSize); 170d8efc6caSAlex Smith lowerHalfIconImage = (uint8 *)gKernelArgs.boot_splash 1717db9fbfeSFrançois Revol + (kSplashIconsWidth * iconsHalfHeight); 1727db9fbfeSFrançois Revol break; 17367938b0dSPhilippe Houdoin default: // 24bits is assumed here 17467938b0dSPhilippe Houdoin uncompressedSize *= 3; 1757db9fbfeSFrançois Revol // pointer into the lower half of the icons image data 1767db9fbfeSFrançois Revol gKernelArgs.boot_splash 17767938b0dSPhilippe Houdoin = (uint8*)kernel_args_malloc(uncompressedSize); 17862d36f98SAlex Smith if (gKernelArgs.boot_splash == NULL) 1797db9fbfeSFrançois Revol return B_NO_MEMORY; 18067938b0dSPhilippe Houdoin uncompress(kSplashIcons24BitCompressedImage, 18167938b0dSPhilippe Houdoin sizeof(kSplashIcons24BitCompressedImage), 18267938b0dSPhilippe Houdoin gKernelArgs.boot_splash, uncompressedSize); 183d8efc6caSAlex Smith lowerHalfIconImage = (uint8 *)gKernelArgs.boot_splash 1847db9fbfeSFrançois Revol + (kSplashIconsWidth * iconsHalfHeight) * 3; 1857db9fbfeSFrançois Revol break; 1867db9fbfeSFrançois Revol } 1877db9fbfeSFrançois Revol 1887db9fbfeSFrançois Revol // render initial (grayed out) icons 1897db9fbfeSFrançois Revol // the grayed out version is the lower half of the icons image 1907db9fbfeSFrançois Revol 1917db9fbfeSFrançois Revol width = min_c(kSplashIconsWidth, gKernelArgs.frame_buffer.width); 1927db9fbfeSFrançois Revol height = min_c(kSplashLogoHeight + iconsHalfHeight, 1937db9fbfeSFrançois Revol gKernelArgs.frame_buffer.height); 1947db9fbfeSFrançois Revol placementX = max_c(0, min_c(100, kSplashIconsPlacementX)); 1957db9fbfeSFrançois Revol placementY = max_c(0, min_c(100, kSplashIconsPlacementY)); 1967db9fbfeSFrançois Revol 1977db9fbfeSFrançois Revol x = (gKernelArgs.frame_buffer.width - width) * placementX / 100; 1987db9fbfeSFrançois Revol y = kSplashLogoHeight + (gKernelArgs.frame_buffer.height - height) 1997db9fbfeSFrançois Revol * placementY / 100; 2007db9fbfeSFrançois Revol 2017db9fbfeSFrançois Revol height = min_c(iconsHalfHeight, gKernelArgs.frame_buffer.height); 2027db9fbfeSFrançois Revol video_blit_image(frameBuffer, lowerHalfIconImage, width, height, 2037db9fbfeSFrançois Revol kSplashIconsWidth, x, y); 204477d2636SFrançois Revol return B_OK; 2057db9fbfeSFrançois Revol } 2067db9fbfeSFrançois Revol 20767938b0dSPhilippe Houdoin 20867938b0dSPhilippe Houdoin 209