]> git.proxmox.com Git - mirror_edk2.git/blob - EdkCompatibilityPkg/Foundation/Library/Dxe/GraphicsLite/Graphics.c
5123aacf4573109663eb826af4d7ff4aa43526b8
[mirror_edk2.git] / EdkCompatibilityPkg / Foundation / Library / Dxe / GraphicsLite / Graphics.c
1 /*++
2
3 Copyright (c) 2004 - 2012, 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 UINTN DataSizePerLine;
167 BOOLEAN IsAllocated;
168 UINT32 ColorMapNum;
169
170 if (sizeof (BMP_IMAGE_HEADER) > BmpImageSize) {
171 return EFI_INVALID_PARAMETER;
172 }
173
174 BmpHeader = (BMP_IMAGE_HEADER *) BmpImage;
175
176 if (BmpHeader->CharB != 'B' || BmpHeader->CharM != 'M') {
177 return EFI_UNSUPPORTED;
178 }
179
180 //
181 // Doesn't support compress.
182 //
183 if (BmpHeader->CompressionType != 0) {
184 return EFI_UNSUPPORTED;
185 }
186
187 //
188 // Only support BITMAPINFOHEADER format.
189 // BITMAPFILEHEADER + BITMAPINFOHEADER = BMP_IMAGE_HEADER
190 //
191 if (BmpHeader->HeaderSize != sizeof (BMP_IMAGE_HEADER) - ((UINTN) &(((BMP_IMAGE_HEADER *)0)->HeaderSize))) {
192 return EFI_UNSUPPORTED;
193 }
194
195 //
196 // The data size in each line must be 4 byte alignment.
197 //
198 DataSizePerLine = ((BmpHeader->PixelWidth * BmpHeader->BitPerPixel + 31) >> 3) & (~0x3);
199 BltBufferSize = MultU64x32 (DataSizePerLine, BmpHeader->PixelHeight);
200 if (BltBufferSize > (UINT32) ~0) {
201 return EFI_INVALID_PARAMETER;
202 }
203
204 if ((BmpHeader->Size != BmpImageSize) ||
205 (BmpHeader->Size < BmpHeader->ImageOffset) ||
206 (BmpHeader->Size - BmpHeader->ImageOffset != BmpHeader->PixelHeight * DataSizePerLine)) {
207 return EFI_INVALID_PARAMETER;
208 }
209
210 //
211 // Calculate Color Map offset in the image.
212 //
213 Image = BmpImage;
214 BmpColorMap = (BMP_COLOR_MAP *) (Image + sizeof (BMP_IMAGE_HEADER));
215 if (BmpHeader->ImageOffset < sizeof (BMP_IMAGE_HEADER)) {
216 return EFI_INVALID_PARAMETER;
217 }
218
219 if (BmpHeader->ImageOffset > sizeof (BMP_IMAGE_HEADER)) {
220 switch (BmpHeader->BitPerPixel) {
221 case 1:
222 ColorMapNum = 2;
223 break;
224 case 4:
225 ColorMapNum = 16;
226 break;
227 case 8:
228 ColorMapNum = 256;
229 break;
230 default:
231 ColorMapNum = 0;
232 break;
233 }
234 if (BmpHeader->ImageOffset - sizeof (BMP_IMAGE_HEADER) != sizeof (BMP_COLOR_MAP) * ColorMapNum) {
235 return EFI_INVALID_PARAMETER;
236 }
237 }
238
239 //
240 // Calculate graphics image data address in the image
241 //
242 Image = ((UINT8 *) BmpImage) + BmpHeader->ImageOffset;
243 ImageHeader = Image;
244
245 BltBufferSize = MultU64x32 ((UINT64) BmpHeader->PixelWidth, BmpHeader->PixelHeight);
246 //
247 // Ensure the BltBufferSize * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) doesn't overflow
248 //
249 if (BltBufferSize > DivU64x32 ((UINTN) ~0, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), NULL)) {
250 return EFI_UNSUPPORTED;
251 }
252 BltBufferSize = MultU64x32 (BltBufferSize, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
253
254 IsAllocated = FALSE;
255 if (*GopBlt == NULL) {
256 *GopBltSize = (UINTN) BltBufferSize;
257 *GopBlt = EfiLibAllocatePool (*GopBltSize);
258 IsAllocated = TRUE;
259 if (*GopBlt == NULL) {
260 return EFI_OUT_OF_RESOURCES;
261 }
262 } else {
263 if (*GopBltSize < (UINTN) BltBufferSize) {
264 *GopBltSize = (UINTN) BltBufferSize;
265 return EFI_BUFFER_TOO_SMALL;
266 }
267 }
268
269 *PixelWidth = BmpHeader->PixelWidth;
270 *PixelHeight = BmpHeader->PixelHeight;
271
272 //
273 // Convert image from BMP to Blt buffer format
274 //
275 BltBuffer = *GopBlt;
276 for (Height = 0; Height < BmpHeader->PixelHeight; Height++) {
277 Blt = &BltBuffer[(BmpHeader->PixelHeight - Height - 1) * BmpHeader->PixelWidth];
278 for (Width = 0; Width < BmpHeader->PixelWidth; Width++, Image++, Blt++) {
279 switch (BmpHeader->BitPerPixel) {
280 case 1:
281 //
282 // Convert 1bit BMP to 24-bit color
283 //
284 for (Index = 0; Index < 8 && Width < BmpHeader->PixelWidth; Index++) {
285 Blt->Red = BmpColorMap[((*Image) >> (7 - Index)) & 0x1].Red;
286 Blt->Green = BmpColorMap[((*Image) >> (7 - Index)) & 0x1].Green;
287 Blt->Blue = BmpColorMap[((*Image) >> (7 - Index)) & 0x1].Blue;
288 Blt++;
289 Width++;
290 }
291
292 Blt --;
293 Width --;
294 break;
295
296 case 4:
297 //
298 // Convert BMP Palette to 24-bit color
299 //
300 Index = (*Image) >> 4;
301 Blt->Red = BmpColorMap[Index].Red;
302 Blt->Green = BmpColorMap[Index].Green;
303 Blt->Blue = BmpColorMap[Index].Blue;
304 if (Width < (BmpHeader->PixelWidth - 1)) {
305 Blt++;
306 Width++;
307 Index = (*Image) & 0x0f;
308 Blt->Red = BmpColorMap[Index].Red;
309 Blt->Green = BmpColorMap[Index].Green;
310 Blt->Blue = BmpColorMap[Index].Blue;
311 }
312 break;
313
314 case 8:
315 //
316 // Convert BMP Palette to 24-bit color
317 //
318 Blt->Red = BmpColorMap[*Image].Red;
319 Blt->Green = BmpColorMap[*Image].Green;
320 Blt->Blue = BmpColorMap[*Image].Blue;
321 break;
322
323 case 24:
324 Blt->Blue = *Image++;
325 Blt->Green = *Image++;
326 Blt->Red = *Image;
327 break;
328
329 default:
330 if (IsAllocated) {
331 gBS->FreePool (*GopBlt);
332 *GopBlt = NULL;
333 }
334 return EFI_UNSUPPORTED;
335 break;
336 };
337
338 }
339
340 ImageIndex = (UINTN) (Image - ImageHeader);
341 if ((ImageIndex % 4) != 0) {
342 //
343 // Bmp Image starts each row on a 32-bit boundary!
344 //
345 Image = Image + (4 - (ImageIndex % 4));
346 }
347 }
348
349 return EFI_SUCCESS;
350 }
351
352
353 EFI_STATUS
354 LockKeyboards (
355 IN CHAR16 *Password
356 )
357 /*++
358
359 Routine Description:
360 Use Console Control Protocol to lock the Console In Spliter virtual handle.
361 This is the ConInHandle and ConIn handle in the EFI system table. All key
362 presses will be ignored until the Password is typed in. The only way to
363 disable the password is to type it in to a ConIn device.
364
365 Arguments:
366 Password - Password used to lock ConIn device
367
368
369 Returns:
370
371 EFI_SUCCESS - ConsoleControl has been flipped to graphics and logo
372 displayed.
373 EFI_UNSUPPORTED - Logo not found
374
375 --*/
376 {
377 EFI_STATUS Status;
378 EFI_CONSOLE_CONTROL_PROTOCOL *ConsoleControl;
379
380 Status = gBS->LocateProtocol (&gEfiConsoleControlProtocolGuid, NULL, (VOID **) &ConsoleControl);
381 if (EFI_ERROR (Status)) {
382 return EFI_UNSUPPORTED;
383 }
384
385 Status = ConsoleControl->LockStdIn (ConsoleControl, Password);
386 return Status;
387 }
388
389 EFI_STATUS
390 EnableQuietBoot (
391 IN EFI_GUID *LogoFile
392 )
393 /*++
394
395 Routine Description:
396
397 Use Console Control to turn off UGA based Simple Text Out consoles from going
398 to the UGA device. Put up LogoFile on every UGA device that is a console
399
400 Arguments:
401
402 LogoFile - File name of logo to display on the center of the screen.
403
404
405 Returns:
406
407 EFI_SUCCESS - ConsoleControl has been flipped to graphics and logo
408 displayed.
409 EFI_UNSUPPORTED - Logo not found
410
411 --*/
412 {
413 return EnableQuietBootEx (LogoFile, NULL);
414 }
415
416
417 EFI_STATUS
418 EnableQuietBootEx (
419 IN EFI_GUID *LogoFile,
420 IN EFI_HANDLE ImageHandle
421 )
422 /*++
423
424 Routine Description:
425
426 Use Console Control to turn off GOP/UGA based Simple Text Out consoles from going
427 to the GOP/UGA device. Put up LogoFile on every GOP/UGA device that is a console
428
429 Arguments:
430
431 LogoFile - File name of logo to display on the center of the screen.
432
433
434 Returns:
435
436 EFI_SUCCESS - ConsoleControl has been flipped to graphics and logo
437 displayed.
438 EFI_UNSUPPORTED - Logo not found
439
440 --*/
441 {
442 EFI_STATUS Status;
443 EFI_CONSOLE_CONTROL_PROTOCOL *ConsoleControl;
444 EFI_OEM_BADGING_PROTOCOL *Badging;
445 UINT32 SizeOfX;
446 UINT32 SizeOfY;
447 INTN DestX;
448 INTN DestY;
449 UINT8 *ImageData;
450 UINTN ImageSize;
451 UINTN BltSize;
452 UINT32 Instance;
453 EFI_BADGING_FORMAT Format;
454 EFI_BADGING_DISPLAY_ATTRIBUTE Attribute;
455 UINTN CoordinateX;
456 UINTN CoordinateY;
457 UINTN Height;
458 UINTN Width;
459 EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Blt;
460 EFI_UGA_DRAW_PROTOCOL *UgaDraw;
461 UINT32 ColorDepth;
462 UINT32 RefreshRate;
463 EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
464
465 Status = gBS->LocateProtocol (&gEfiConsoleControlProtocolGuid, NULL, (VOID **) &ConsoleControl);
466 if (EFI_ERROR (Status)) {
467 return EFI_UNSUPPORTED;
468 }
469
470 UgaDraw = NULL;
471 //
472 // Try to open GOP first
473 //
474 Status = gBS->HandleProtocol (gST->ConsoleOutHandle, &gEfiGraphicsOutputProtocolGuid, (VOID **) &GraphicsOutput);
475 if (EFI_ERROR (Status)) {
476 GraphicsOutput = NULL;
477 //
478 // Open GOP failed, try to open UGA
479 //
480 Status = gBS->HandleProtocol (gST->ConsoleOutHandle, &gEfiUgaDrawProtocolGuid, (VOID **) &UgaDraw);
481 if (EFI_ERROR (Status)) {
482 return EFI_UNSUPPORTED;
483 }
484 }
485
486 Badging = NULL;
487 Status = gBS->LocateProtocol (&gEfiOEMBadgingProtocolGuid, NULL, (VOID **) &Badging);
488
489 ConsoleControl->SetMode (ConsoleControl, EfiConsoleControlScreenGraphics);
490
491 if (GraphicsOutput != NULL) {
492 SizeOfX = GraphicsOutput->Mode->Info->HorizontalResolution;
493 SizeOfY = GraphicsOutput->Mode->Info->VerticalResolution;
494 } else if (UgaDraw != NULL) {
495 Status = UgaDraw->GetMode (UgaDraw, &SizeOfX, &SizeOfY, &ColorDepth, &RefreshRate);
496 if (EFI_ERROR (Status)) {
497 return EFI_UNSUPPORTED;
498 }
499 } else {
500 return EFI_UNSUPPORTED;
501 }
502
503 Instance = 0;
504 while (1) {
505 ImageData = NULL;
506 ImageSize = 0;
507
508 if (Badging != NULL) {
509 Status = Badging->GetImage (
510 Badging,
511 &Instance,
512 &Format,
513 &ImageData,
514 &ImageSize,
515 &Attribute,
516 &CoordinateX,
517 &CoordinateY
518 );
519 if (EFI_ERROR (Status)) {
520 return Status;
521 }
522
523 //
524 // Currently only support BMP format
525 //
526 if (Format != EfiBadgingFormatBMP) {
527 gBS->FreePool (ImageData);
528 continue;
529 }
530 } else {
531 Status = GetGraphicsBitMapFromFVEx (ImageHandle, LogoFile, (VOID **) &ImageData, &ImageSize);
532 if (EFI_ERROR (Status)) {
533 return EFI_UNSUPPORTED;
534 }
535
536 CoordinateX = 0;
537 CoordinateY = 0;
538 Attribute = EfiBadgingDisplayAttributeCenter;
539 }
540
541 Blt = NULL;
542 Status = ConvertBmpToGopBlt (
543 ImageData,
544 ImageSize,
545 (VOID **) &Blt,
546 &BltSize,
547 &Height,
548 &Width
549 );
550 if (EFI_ERROR (Status)) {
551 gBS->FreePool (ImageData);
552 if (Badging == NULL) {
553 return Status;
554 } else {
555 continue;
556 }
557 }
558
559 switch (Attribute) {
560 case EfiBadgingDisplayAttributeLeftTop:
561 DestX = CoordinateX;
562 DestY = CoordinateY;
563 break;
564
565 case EfiBadgingDisplayAttributeCenterTop:
566 DestX = (SizeOfX - Width) / 2;
567 DestY = CoordinateY;
568 break;
569
570 case EfiBadgingDisplayAttributeRightTop:
571 DestX = (SizeOfX - Width - CoordinateX);
572 DestY = CoordinateY;;
573 break;
574
575 case EfiBadgingDisplayAttributeCenterRight:
576 DestX = (SizeOfX - Width - CoordinateX);
577 DestY = (SizeOfY - Height) / 2;
578 break;
579
580 case EfiBadgingDisplayAttributeRightBottom:
581 DestX = (SizeOfX - Width - CoordinateX);
582 DestY = (SizeOfY - Height - CoordinateY);
583 break;
584
585 case EfiBadgingDisplayAttributeCenterBottom:
586 DestX = (SizeOfX - Width) / 2;
587 DestY = (SizeOfY - Height - CoordinateY);
588 break;
589
590 case EfiBadgingDisplayAttributeLeftBottom:
591 DestX = CoordinateX;
592 DestY = (SizeOfY - Height - CoordinateY);
593 break;
594
595 case EfiBadgingDisplayAttributeCenterLeft:
596 DestX = CoordinateX;
597 DestY = (SizeOfY - Height) / 2;
598 break;
599
600 case EfiBadgingDisplayAttributeCenter:
601 DestX = (SizeOfX - Width) / 2;
602 DestY = (SizeOfY - Height) / 2;
603 break;
604
605 default:
606 DestX = CoordinateX;
607 DestY = CoordinateY;
608 break;
609 }
610
611 if ((DestX >= 0) && (DestY >= 0)) {
612 if (GraphicsOutput != NULL) {
613 Status = GraphicsOutput->Blt (
614 GraphicsOutput,
615 Blt,
616 EfiBltBufferToVideo,
617 0,
618 0,
619 (UINTN) DestX,
620 (UINTN) DestY,
621 Width,
622 Height,
623 Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
624 );
625 } else {
626 Status = UgaDraw->Blt (
627 UgaDraw,
628 (EFI_UGA_PIXEL *) Blt,
629 EfiUgaBltBufferToVideo,
630 0,
631 0,
632 (UINTN) DestX,
633 (UINTN) DestY,
634 Width,
635 Height,
636 Width * sizeof (EFI_UGA_PIXEL)
637 );
638 }
639 }
640
641 gBS->FreePool (ImageData);
642 gBS->FreePool (Blt);
643
644 if (Badging == NULL) {
645 break;
646 }
647 }
648
649 return Status;
650 }
651
652
653 EFI_STATUS
654 DisableQuietBoot (
655 VOID
656 )
657 /*++
658
659 Routine Description:
660
661 Use Console Control to turn on GOP/UGA based Simple Text Out consoles. The GOP/UGA
662 Simple Text Out screens will now be synced up with all non GOP/UGA output devices
663
664 Arguments:
665
666 NONE
667
668 Returns:
669
670 EFI_SUCCESS - GOP/UGA devices are back in text mode and synced up.
671 EFI_UNSUPPORTED - Logo not found
672
673 --*/
674 {
675 EFI_STATUS Status;
676 EFI_CONSOLE_CONTROL_PROTOCOL *ConsoleControl;
677
678 Status = gBS->LocateProtocol (&gEfiConsoleControlProtocolGuid, NULL, (VOID **) &ConsoleControl);
679 if (EFI_ERROR (Status)) {
680 return EFI_UNSUPPORTED;
681 }
682
683 return ConsoleControl->SetMode (ConsoleControl, EfiConsoleControlScreenText);
684 }