1 /* 2 * Copyright 2004-2009, Axel Dörfler, axeld@pinc-software.de. 3 * Copyright 2008, Stephan Aßmus <superstippi@gmx.de> 4 * Copyright 2008, Philippe Saint-Pierre <stpere@gmail.com> 5 * Distributed under the terms of the MIT License. 6 */ 7 8 9 #include <arch/cpu.h> 10 #include <boot/stage2.h> 11 #include <boot/platform.h> 12 #include <boot/menu.h> 13 #include <boot/kernel_args.h> 14 #include <boot/platform/generic/video.h> 15 #include <boot/images.h> 16 17 #include <stdio.h> 18 #include <stdlib.h> 19 20 #include <zlib.h> 21 22 23 //#define TRACE_VIDEO 24 #ifdef TRACE_VIDEO 25 # define TRACE(x) dprintf x 26 #else 27 # define TRACE(x) ; 28 #endif 29 30 31 static status_t 32 uncompress(const uint8 compressed[], unsigned int compressedSize, 33 uint8* uncompressed, unsigned int uncompressedSize) 34 { 35 if (compressedSize == 0 || uncompressedSize == 0) 36 return B_BAD_VALUE; 37 38 // prepare zlib stream 39 z_stream zStream = { 40 (Bytef*)compressed, // next_in 41 compressedSize, // avail_in 42 0, // total_in 43 (Bytef*)uncompressed, // next_out 44 uncompressedSize, // avail_out 45 0, // total_out 46 0, // msg 47 0, // state 48 Z_NULL, // zalloc (kernel_args_malloc?) 49 Z_NULL, // zfree (kernel_args_free?) 50 Z_NULL, // opaque 51 0, // data_type 52 0, // adler 53 0 // reserved 54 }; 55 56 int zlibError = inflateInit(&zStream); 57 if (zlibError != Z_OK) 58 return B_ERROR; // TODO: translate zlibError 59 60 // inflate 61 status_t status = B_OK; 62 zlibError = inflate(&zStream, Z_FINISH); 63 if (zlibError != Z_STREAM_END) { 64 if (zlibError == Z_OK) 65 status = B_BUFFER_OVERFLOW; 66 else 67 status = B_ERROR; // TODO: translate zlibError 68 } 69 70 // clean up 71 zlibError = inflateEnd(&zStream); 72 if (zlibError != Z_OK && status == B_OK) 73 status = B_ERROR; // TODO: translate zlibError 74 75 if (status == B_OK && zStream.total_out != uncompressedSize) 76 status = B_ERROR; 77 78 return status; 79 } 80 81 82 extern "C" status_t 83 video_display_splash(addr_t frameBuffer) 84 { 85 if (!gKernelArgs.frame_buffer.enabled) 86 return B_NO_INIT; 87 88 addr_t pos = 0; 89 // Limit area to clear to estimated screen area 90 // UEFI can happily report a >256M framebuffer 91 addr_t size = min_c(gKernelArgs.frame_buffer.width 92 * gKernelArgs.frame_buffer.height * 4u, 93 gKernelArgs.frame_buffer.physical_buffer.size); 94 95 if (size >= 64) { 96 // Align writes 97 for (addr_t align = (8 - (frameBuffer & 7)) & 7; pos < align; pos++) 98 *(char*)(frameBuffer + pos) = 0; 99 // Write eight bytes, many many times, but not too many 100 for (addr_t alignSize = size - 8; pos < alignSize; pos +=8) { 101 *(uint32*)(frameBuffer + pos) = 0; 102 *(uint32*)(frameBuffer + pos + 4) = 0; 103 } 104 } 105 // Write a few bytes more 106 for (; pos < size; pos++) 107 *(char*)(frameBuffer + pos) = 0; 108 109 uint8* uncompressedLogo = NULL; 110 unsigned int uncompressedSize = kSplashLogoWidth * kSplashLogoHeight; 111 switch (gKernelArgs.frame_buffer.depth) { 112 case 8: 113 platform_set_palette(k8BitPalette); 114 uncompressedLogo = (uint8*)kernel_args_malloc(uncompressedSize); 115 if (uncompressedLogo == NULL) 116 return B_NO_MEMORY; 117 118 uncompress(kSplashLogo8BitCompressedImage, 119 sizeof(kSplashLogo8BitCompressedImage), uncompressedLogo, 120 uncompressedSize); 121 break; 122 default: // 24 bits is assumed here 123 uncompressedSize *= 3; 124 uncompressedLogo = (uint8*)kernel_args_malloc(uncompressedSize); 125 if (uncompressedLogo == NULL) 126 return B_NO_MEMORY; 127 128 uncompress(kSplashLogo24BitCompressedImage, 129 sizeof(kSplashLogo24BitCompressedImage), uncompressedLogo, 130 uncompressedSize); 131 break; 132 } 133 134 // TODO: support 4-bit indexed version of the images! 135 136 // render splash logo 137 uint16 iconsHalfHeight = kSplashIconsHeight / 2; 138 139 int width = min_c(kSplashLogoWidth, gKernelArgs.frame_buffer.width); 140 int height = min_c(kSplashLogoHeight + iconsHalfHeight, 141 gKernelArgs.frame_buffer.height); 142 int placementX = max_c(0, min_c(100, kSplashLogoPlacementX)); 143 int placementY = max_c(0, min_c(100, kSplashLogoPlacementY)); 144 145 int x = (gKernelArgs.frame_buffer.width - width) * placementX / 100; 146 int y = (gKernelArgs.frame_buffer.height - height) * placementY / 100; 147 148 height = min_c(kSplashLogoHeight, gKernelArgs.frame_buffer.height); 149 switch (gKernelArgs.frame_buffer.depth) { 150 case 8: 151 break; 152 } 153 video_blit_image(frameBuffer, uncompressedLogo, width, height, 154 kSplashLogoWidth, x, y); 155 156 kernel_args_free(uncompressedLogo); 157 158 const uint8* lowerHalfIconImage; 159 uncompressedSize = kSplashIconsWidth * kSplashIconsHeight; 160 switch (gKernelArgs.frame_buffer.depth) { 161 case 8: 162 // pointer into the lower half of the icons image data 163 gKernelArgs.boot_splash 164 = (uint8*)kernel_args_malloc(uncompressedSize); 165 if (gKernelArgs.boot_splash == NULL) 166 return B_NO_MEMORY; 167 uncompress(kSplashIcons8BitCompressedImage, 168 sizeof(kSplashIcons8BitCompressedImage), 169 gKernelArgs.boot_splash, uncompressedSize); 170 lowerHalfIconImage = (uint8 *)gKernelArgs.boot_splash 171 + (kSplashIconsWidth * iconsHalfHeight); 172 break; 173 default: // 24bits is assumed here 174 uncompressedSize *= 3; 175 // pointer into the lower half of the icons image data 176 gKernelArgs.boot_splash 177 = (uint8*)kernel_args_malloc(uncompressedSize); 178 if (gKernelArgs.boot_splash == NULL) 179 return B_NO_MEMORY; 180 uncompress(kSplashIcons24BitCompressedImage, 181 sizeof(kSplashIcons24BitCompressedImage), 182 gKernelArgs.boot_splash, uncompressedSize); 183 lowerHalfIconImage = (uint8 *)gKernelArgs.boot_splash 184 + (kSplashIconsWidth * iconsHalfHeight) * 3; 185 break; 186 } 187 188 // render initial (grayed out) icons 189 // the grayed out version is the lower half of the icons image 190 191 width = min_c(kSplashIconsWidth, gKernelArgs.frame_buffer.width); 192 height = min_c(kSplashLogoHeight + iconsHalfHeight, 193 gKernelArgs.frame_buffer.height); 194 placementX = max_c(0, min_c(100, kSplashIconsPlacementX)); 195 placementY = max_c(0, min_c(100, kSplashIconsPlacementY)); 196 197 x = (gKernelArgs.frame_buffer.width - width) * placementX / 100; 198 y = kSplashLogoHeight + (gKernelArgs.frame_buffer.height - height) 199 * placementY / 100; 200 201 height = min_c(iconsHalfHeight, gKernelArgs.frame_buffer.height); 202 video_blit_image(frameBuffer, lowerHalfIconImage, width, height, 203 kSplashIconsWidth, x, y); 204 return B_OK; 205 } 206 207 208 209