]> git.proxmox.com Git - mirror_edk2.git/blob - EdkCompatibilityPkg/Foundation/Library/Dxe/GraphicsLite/Graphics.c
Add more check to make sure code run safely.
[mirror_edk2.git] / EdkCompatibilityPkg / Foundation / Library / Dxe / GraphicsLite / Graphics.c
1 /*++
2
3 Copyright (c) 2004 - 2010, Intel Corporation. All rights reserved.<BR>
4 This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
8
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
11
12 Module Name:
13
14 Graphics.c
15
16 Abstract:
17
18 Support for Basic Graphics operations.
19
20 BugBug: Currently *.BMP files are supported. This will be replaced
21 when Tiano graphics format is supported.
22
23 --*/
24
25 #include "Tiano.h"
26 #include "EfiDriverLib.h"
27 #include "GraphicsLib.h"
28
29
30 EFI_STATUS
31 GetGraphicsBitMapFromFV (
32 IN EFI_GUID *FileNameGuid,
33 OUT VOID **Image,
34 OUT UINTN *ImageSize
35 )
36 /*++
37
38 Routine Description:
39
40 Return the graphics image file named FileNameGuid into Image and return it's
41 size in ImageSize. All Firmware Volumes (FV) in the system are searched for the
42 file name.
43
44 Arguments:
45
46 FileNameGuid - File Name of graphics file in the FV(s).
47
48 Image - Pointer to pointer to return graphics image. If NULL, a
49 buffer will be allocated.
50
51 ImageSize - Size of the graphics Image in bytes. Zero if no image found.
52
53
54 Returns:
55
56 EFI_SUCCESS - Image and ImageSize are valid.
57 EFI_BUFFER_TOO_SMALL - Image not big enough. ImageSize has required size
58 EFI_NOT_FOUND - FileNameGuid not found
59
60 --*/
61 {
62 return GetGraphicsBitMapFromFVEx (NULL, FileNameGuid, Image, ImageSize);
63 }
64
65 EFI_STATUS
66 GetGraphicsBitMapFromFVEx (
67 IN EFI_HANDLE ImageHandle,
68 IN EFI_GUID *FileNameGuid,
69 OUT VOID **Image,
70 OUT UINTN *ImageSize
71 )
72 /*++
73
74 Routine Description:
75
76 Return the graphics image file named FileNameGuid into Image and return it's
77 size in ImageSize. All Firmware Volumes (FV) in the system are searched for the
78 file name.
79
80 Arguments:
81
82 ImageHandle - The driver image handle of the caller. The parameter is used to
83 optimize the loading of the image file so that the FV from which
84 the driver image is loaded will be tried first.
85
86 FileNameGuid - File Name of graphics file in the FV(s).
87
88 Image - Pointer to pointer to return graphics image. If NULL, a
89 buffer will be allocated.
90
91 ImageSize - Size of the graphics Image in bytes. Zero if no image found.
92
93
94 Returns:
95
96 EFI_SUCCESS - Image and ImageSize are valid.
97 EFI_BUFFER_TOO_SMALL - Image not big enough. ImageSize has required size
98 EFI_NOT_FOUND - FileNameGuid not found
99
100 --*/
101 {
102 return GetImageEx (
103 ImageHandle,
104 FileNameGuid,
105 EFI_SECTION_RAW,
106 Image,
107 ImageSize,
108 FALSE
109 );
110 }
111
112
113 EFI_STATUS
114 ConvertBmpToGopBlt (
115 IN VOID *BmpImage,
116 IN UINTN BmpImageSize,
117 IN OUT VOID **GopBlt,
118 IN OUT UINTN *GopBltSize,
119 OUT UINTN *PixelHeight,
120 OUT UINTN *PixelWidth
121 )
122 /*++
123
124 Routine Description:
125
126 Convert a *.BMP graphics image to a GOP/UGA blt buffer. If a NULL Blt buffer
127 is passed in a GopBlt buffer will be allocated by this routine. If a GopBlt
128 buffer is passed in it will be used if it is big enough.
129
130 Arguments:
131
132 BmpImage - Pointer to BMP file
133
134 BmpImageSize - Number of bytes in BmpImage
135
136 GopBlt - Buffer containing GOP version of BmpImage.
137
138 GopBltSize - Size of GopBlt in bytes.
139
140 PixelHeight - Height of GopBlt/BmpImage in pixels
141
142 PixelWidth - Width of GopBlt/BmpImage in pixels
143
144
145 Returns:
146
147 EFI_SUCCESS - GopBlt and GopBltSize are returned.
148 EFI_UNSUPPORTED - BmpImage is not a valid *.BMP image
149 EFI_BUFFER_TOO_SMALL - The passed in GopBlt buffer is not big enough.
150 GopBltSize will contain the required size.
151 EFI_OUT_OF_RESOURCES - No enough buffer to allocate
152
153 --*/
154 {
155 UINT8 *Image;
156 UINT8 *ImageHeader;
157 BMP_IMAGE_HEADER *BmpHeader;
158 BMP_COLOR_MAP *BmpColorMap;
159 EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer;
160 EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Blt;
161 UINT64 BltBufferSize;
162 UINTN Index;
163 UINTN Height;
164 UINTN Width;
165 UINTN ImageIndex;
166 BOOLEAN IsAllocated;
167
168 BmpHeader = (BMP_IMAGE_HEADER *) BmpImage;
169 if (BmpHeader->CharB != 'B' || BmpHeader->CharM != 'M') {
170 return EFI_UNSUPPORTED;
171 }
172
173 if (BmpHeader->CompressionType != 0) {
174 return EFI_UNSUPPORTED;
175 }
176
177 //
178 // Calculate Color Map offset in the image.
179 //
180 Image = BmpImage;
181 BmpColorMap = (BMP_COLOR_MAP *) (Image + sizeof (BMP_IMAGE_HEADER));
182
183 //
184 // Calculate graphics image data address in the image
185 //
186 Image = ((UINT8 *) BmpImage) + BmpHeader->ImageOffset;
187 ImageHeader = Image;
188
189 BltBufferSize = MultU64x32 ((UINT64) BmpHeader->PixelWidth, BmpHeader->PixelHeight);
190 //
191 // Ensure the BltBufferSize * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) doesn't overflow
192 //
193 if (BltBufferSize > DivU64x32 ((UINTN) ~0, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), NULL)) {
194 return EFI_UNSUPPORTED;
195 }
196 BltBufferSize = MultU64x32 (BltBufferSize, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
197
198 IsAllocated = FALSE;
199 if (*GopBlt == NULL) {
200 *GopBltSize = (UINTN) BltBufferSize;
201 *GopBlt = EfiLibAllocatePool (*GopBltSize);
202 IsAllocated = TRUE;
203 if (*GopBlt == NULL) {
204 return EFI_OUT_OF_RESOURCES;
205 }
206 } else {
207 if (*GopBltSize < (UINTN) BltBufferSize) {
208 *GopBltSize = (UINTN) BltBufferSize;
209 return EFI_BUFFER_TOO_SMALL;
210 }
211 }
212
213 *PixelWidth = BmpHeader->PixelWidth;
214 *PixelHeight = BmpHeader->PixelHeight;
215
216 //
217 // Convert image from BMP to Blt buffer format
218 //
219 BltBuffer = *GopBlt;
220 for (Height = 0; Height < BmpHeader->PixelHeight; Height++) {
221 Blt = &BltBuffer[(BmpHeader->PixelHeight - Height - 1) * BmpHeader->PixelWidth];
222 for (Width = 0; Width < BmpHeader->PixelWidth; Width++, Image++, Blt++) {
223 switch (BmpHeader->BitPerPixel) {
224 case 1:
225 //
226 // Convert 1bit BMP to 24-bit color
227 //
228 for (Index = 0; Index < 8 && Width < BmpHeader->PixelWidth; Index++) {
229 Blt->Red = BmpColorMap[((*Image) >> (7 - Index)) & 0x1].Red;
230 Blt->Green = BmpColorMap[((*Image) >> (7 - Index)) & 0x1].Green;
231 Blt->Blue = BmpColorMap[((*Image) >> (7 - Index)) & 0x1].Blue;
232 Blt++;
233 Width++;
234 }
235
236 Blt --;
237 Width --;
238 break;
239
240 case 4:
241 //
242 // Convert BMP Palette to 24-bit color
243 //
244 Index = (*Image) >> 4;
245 Blt->Red = BmpColorMap[Index].Red;
246 Blt->Green = BmpColorMap[Index].Green;
247 Blt->Blue = BmpColorMap[Index].Blue;
248 if (Width < (BmpHeader->PixelWidth - 1)) {
249 Blt++;
250 Width++;
251 Index = (*Image) & 0x0f;
252 Blt->Red = BmpColorMap[Index].Red;
253 Blt->Green = BmpColorMap[Index].Green;
254 Blt->Blue = BmpColorMap[Index].Blue;
255 }
256 break;
257
258 case 8:
259 //
260 // Convert BMP Palette to 24-bit color
261 //
262 Blt->Red = BmpColorMap[*Image].Red;
263 Blt->Green = BmpColorMap[*Image].Green;
264 Blt->Blue = BmpColorMap[*Image].Blue;
265 break;
266
267 case 24:
268 Blt->Blue = *Image++;
269 Blt->Green = *Image++;
270 Blt->Red = *Image;
271 break;
272
273 default:
274 if (IsAllocated) {
275 gBS->FreePool (*GopBlt);
276 *GopBlt = NULL;
277 }
278 return EFI_UNSUPPORTED;
279 break;
280 };
281
282 }
283
284 ImageIndex = (UINTN) (Image - ImageHeader);
285 if ((ImageIndex % 4) != 0) {
286 //
287 // Bmp Image starts each row on a 32-bit boundary!
288 //
289 Image = Image + (4 - (ImageIndex % 4));
290 }
291 }
292
293 return EFI_SUCCESS;
294 }
295
296
297 EFI_STATUS
298 LockKeyboards (
299 IN CHAR16 *Password
300 )
301 /*++
302
303 Routine Description:
304 Use Console Control Protocol to lock the Console In Spliter virtual handle.
305 This is the ConInHandle and ConIn handle in the EFI system table. All key
306 presses will be ignored until the Password is typed in. The only way to
307 disable the password is to type it in to a ConIn device.
308
309 Arguments:
310 Password - Password used to lock ConIn device
311
312
313 Returns:
314
315 EFI_SUCCESS - ConsoleControl has been flipped to graphics and logo
316 displayed.
317 EFI_UNSUPPORTED - Logo not found
318
319 --*/
320 {
321 EFI_STATUS Status;
322 EFI_CONSOLE_CONTROL_PROTOCOL *ConsoleControl;
323
324 Status = gBS->LocateProtocol (&gEfiConsoleControlProtocolGuid, NULL, (VOID **) &ConsoleControl);
325 if (EFI_ERROR (Status)) {
326 return EFI_UNSUPPORTED;
327 }
328
329 Status = ConsoleControl->LockStdIn (ConsoleControl, Password);
330 return Status;
331 }
332
333 EFI_STATUS
334 EnableQuietBoot (
335 IN EFI_GUID *LogoFile
336 )
337 /*++
338
339 Routine Description:
340
341 Use Console Control to turn off UGA based Simple Text Out consoles from going
342 to the UGA device. Put up LogoFile on every UGA device that is a console
343
344 Arguments:
345
346 LogoFile - File name of logo to display on the center of the screen.
347
348
349 Returns:
350
351 EFI_SUCCESS - ConsoleControl has been flipped to graphics and logo
352 displayed.
353 EFI_UNSUPPORTED - Logo not found
354
355 --*/
356 {
357 return EnableQuietBootEx (LogoFile, NULL);
358 }
359
360
361 EFI_STATUS
362 EnableQuietBootEx (
363 IN EFI_GUID *LogoFile,
364 IN EFI_HANDLE ImageHandle
365 )
366 /*++
367
368 Routine Description:
369
370 Use Console Control to turn off GOP/UGA based Simple Text Out consoles from going
371 to the GOP/UGA device. Put up LogoFile on every GOP/UGA device that is a console
372
373 Arguments:
374
375 LogoFile - File name of logo to display on the center of the screen.
376
377
378 Returns:
379
380 EFI_SUCCESS - ConsoleControl has been flipped to graphics and logo
381 displayed.
382 EFI_UNSUPPORTED - Logo not found
383
384 --*/
385 {
386 EFI_STATUS Status;
387 EFI_CONSOLE_CONTROL_PROTOCOL *ConsoleControl;
388 EFI_OEM_BADGING_PROTOCOL *Badging;
389 UINT32 SizeOfX;
390 UINT32 SizeOfY;
391 INTN DestX;
392 INTN DestY;
393 UINT8 *ImageData;
394 UINTN ImageSize;
395 UINTN BltSize;
396 UINT32 Instance;
397 EFI_BADGING_FORMAT Format;
398 EFI_BADGING_DISPLAY_ATTRIBUTE Attribute;
399 UINTN CoordinateX;
400 UINTN CoordinateY;
401 UINTN Height;
402 UINTN Width;
403 EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Blt;
404 EFI_UGA_DRAW_PROTOCOL *UgaDraw;
405 UINT32 ColorDepth;
406 UINT32 RefreshRate;
407 EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
408
409 Status = gBS->LocateProtocol (&gEfiConsoleControlProtocolGuid, NULL, (VOID **) &ConsoleControl);
410 if (EFI_ERROR (Status)) {
411 return EFI_UNSUPPORTED;
412 }
413
414 UgaDraw = NULL;
415 //
416 // Try to open GOP first
417 //
418 Status = gBS->HandleProtocol (gST->ConsoleOutHandle, &gEfiGraphicsOutputProtocolGuid, (VOID **) &GraphicsOutput);
419 if (EFI_ERROR (Status)) {
420 GraphicsOutput = NULL;
421 //
422 // Open GOP failed, try to open UGA
423 //
424 Status = gBS->HandleProtocol (gST->ConsoleOutHandle, &gEfiUgaDrawProtocolGuid, (VOID **) &UgaDraw);
425 if (EFI_ERROR (Status)) {
426 return EFI_UNSUPPORTED;
427 }
428 }
429
430 Badging = NULL;
431 Status = gBS->LocateProtocol (&gEfiOEMBadgingProtocolGuid, NULL, (VOID **) &Badging);
432
433 ConsoleControl->SetMode (ConsoleControl, EfiConsoleControlScreenGraphics);
434
435 if (GraphicsOutput != NULL) {
436 SizeOfX = GraphicsOutput->Mode->Info->HorizontalResolution;
437 SizeOfY = GraphicsOutput->Mode->Info->VerticalResolution;
438 } else if (UgaDraw != NULL) {
439 Status = UgaDraw->GetMode (UgaDraw, &SizeOfX, &SizeOfY, &ColorDepth, &RefreshRate);
440 if (EFI_ERROR (Status)) {
441 return EFI_UNSUPPORTED;
442 }
443 } else {
444 return EFI_UNSUPPORTED;
445 }
446
447 Instance = 0;
448 while (1) {
449 ImageData = NULL;
450 ImageSize = 0;
451
452 if (Badging != NULL) {
453 Status = Badging->GetImage (
454 Badging,
455 &Instance,
456 &Format,
457 &ImageData,
458 &ImageSize,
459 &Attribute,
460 &CoordinateX,
461 &CoordinateY
462 );
463 if (EFI_ERROR (Status)) {
464 return Status;
465 }
466
467 //
468 // Currently only support BMP format
469 //
470 if (Format != EfiBadgingFormatBMP) {
471 gBS->FreePool (ImageData);
472 continue;
473 }
474 } else {
475 Status = GetGraphicsBitMapFromFVEx (ImageHandle, LogoFile, (VOID **) &ImageData, &ImageSize);
476 if (EFI_ERROR (Status)) {
477 return EFI_UNSUPPORTED;
478 }
479
480 CoordinateX = 0;
481 CoordinateY = 0;
482 Attribute = EfiBadgingDisplayAttributeCenter;
483 }
484
485 Blt = NULL;
486 Status = ConvertBmpToGopBlt (
487 ImageData,
488 ImageSize,
489 (VOID **) &Blt,
490 &BltSize,
491 &Height,
492 &Width
493 );
494 if (EFI_ERROR (Status)) {
495 gBS->FreePool (ImageData);
496 if (Badging == NULL) {
497 return Status;
498 } else {
499 continue;
500 }
501 }
502
503 switch (Attribute) {
504 case EfiBadgingDisplayAttributeLeftTop:
505 DestX = CoordinateX;
506 DestY = CoordinateY;
507 break;
508
509 case EfiBadgingDisplayAttributeCenterTop:
510 DestX = (SizeOfX - Width) / 2;
511 DestY = CoordinateY;
512 break;
513
514 case EfiBadgingDisplayAttributeRightTop:
515 DestX = (SizeOfX - Width - CoordinateX);
516 DestY = CoordinateY;;
517 break;
518
519 case EfiBadgingDisplayAttributeCenterRight:
520 DestX = (SizeOfX - Width - CoordinateX);
521 DestY = (SizeOfY - Height) / 2;
522 break;
523
524 case EfiBadgingDisplayAttributeRightBottom:
525 DestX = (SizeOfX - Width - CoordinateX);
526 DestY = (SizeOfY - Height - CoordinateY);
527 break;
528
529 case EfiBadgingDisplayAttributeCenterBottom:
530 DestX = (SizeOfX - Width) / 2;
531 DestY = (SizeOfY - Height - CoordinateY);
532 break;
533
534 case EfiBadgingDisplayAttributeLeftBottom:
535 DestX = CoordinateX;
536 DestY = (SizeOfY - Height - CoordinateY);
537 break;
538
539 case EfiBadgingDisplayAttributeCenterLeft:
540 DestX = CoordinateX;
541 DestY = (SizeOfY - Height) / 2;
542 break;
543
544 case EfiBadgingDisplayAttributeCenter:
545 DestX = (SizeOfX - Width) / 2;
546 DestY = (SizeOfY - Height) / 2;
547 break;
548
549 default:
550 DestX = CoordinateX;
551 DestY = CoordinateY;
552 break;
553 }
554
555 if ((DestX >= 0) && (DestY >= 0)) {
556 if (GraphicsOutput != NULL) {
557 Status = GraphicsOutput->Blt (
558 GraphicsOutput,
559 Blt,
560 EfiBltBufferToVideo,
561 0,
562 0,
563 (UINTN) DestX,
564 (UINTN) DestY,
565 Width,
566 Height,
567 Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
568 );
569 } else {
570 Status = UgaDraw->Blt (
571 UgaDraw,
572 (EFI_UGA_PIXEL *) Blt,
573 EfiUgaBltBufferToVideo,
574 0,
575 0,
576 (UINTN) DestX,
577 (UINTN) DestY,
578 Width,
579 Height,
580 Width * sizeof (EFI_UGA_PIXEL)
581 );
582 }
583 }
584
585 gBS->FreePool (ImageData);
586 gBS->FreePool (Blt);
587
588 if (Badging == NULL) {
589 break;
590 }
591 }
592
593 return Status;
594 }
595
596
597 EFI_STATUS
598 DisableQuietBoot (
599 VOID
600 )
601 /*++
602
603 Routine Description:
604
605 Use Console Control to turn on GOP/UGA based Simple Text Out consoles. The GOP/UGA
606 Simple Text Out screens will now be synced up with all non GOP/UGA output devices
607
608 Arguments:
609
610 NONE
611
612 Returns:
613
614 EFI_SUCCESS - GOP/UGA devices are back in text mode and synced up.
615 EFI_UNSUPPORTED - Logo not found
616
617 --*/
618 {
619 EFI_STATUS Status;
620 EFI_CONSOLE_CONTROL_PROTOCOL *ConsoleControl;
621
622 Status = gBS->LocateProtocol (&gEfiConsoleControlProtocolGuid, NULL, (VOID **) &ConsoleControl);
623 if (EFI_ERROR (Status)) {
624 return EFI_UNSUPPORTED;
625 }
626
627 return ConsoleControl->SetMode (ConsoleControl, EfiConsoleControlScreenText);
628 }