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