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