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