]> git.proxmox.com Git - mirror_edk2.git/blob - EdkCompatibilityPkg/Foundation/Library/Dxe/GraphicsLite/Graphics.c
Update the copyright notice format
[mirror_edk2.git] / EdkCompatibilityPkg / Foundation / Library / Dxe / GraphicsLite / Graphics.c
1 /*++
2
3 Copyright (c) 2004 - 2009, 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 {
439 Status = UgaDraw->GetMode (UgaDraw, &SizeOfX, &SizeOfY, &ColorDepth, &RefreshRate);
440 if (EFI_ERROR (Status)) {
441 return EFI_UNSUPPORTED;
442 }
443 }
444
445 Instance = 0;
446 while (1) {
447 ImageData = NULL;
448 ImageSize = 0;
449
450 if (Badging != NULL) {
451 Status = Badging->GetImage (
452 Badging,
453 &Instance,
454 &Format,
455 &ImageData,
456 &ImageSize,
457 &Attribute,
458 &CoordinateX,
459 &CoordinateY
460 );
461 if (EFI_ERROR (Status)) {
462 return Status;
463 }
464
465 //
466 // Currently only support BMP format
467 //
468 if (Format != EfiBadgingFormatBMP) {
469 gBS->FreePool (ImageData);
470 continue;
471 }
472 } else {
473 Status = GetGraphicsBitMapFromFVEx (ImageHandle, LogoFile, (VOID **) &ImageData, &ImageSize);
474 if (EFI_ERROR (Status)) {
475 return EFI_UNSUPPORTED;
476 }
477
478 CoordinateX = 0;
479 CoordinateY = 0;
480 Attribute = EfiBadgingDisplayAttributeCenter;
481 }
482
483 Blt = NULL;
484 Status = ConvertBmpToGopBlt (
485 ImageData,
486 ImageSize,
487 (VOID **) &Blt,
488 &BltSize,
489 &Height,
490 &Width
491 );
492 if (EFI_ERROR (Status)) {
493 gBS->FreePool (ImageData);
494 if (Badging == NULL) {
495 return Status;
496 } else {
497 continue;
498 }
499 }
500
501 switch (Attribute) {
502 case EfiBadgingDisplayAttributeLeftTop:
503 DestX = CoordinateX;
504 DestY = CoordinateY;
505 break;
506
507 case EfiBadgingDisplayAttributeCenterTop:
508 DestX = (SizeOfX - Width) / 2;
509 DestY = CoordinateY;
510 break;
511
512 case EfiBadgingDisplayAttributeRightTop:
513 DestX = (SizeOfX - Width - CoordinateX);
514 DestY = CoordinateY;;
515 break;
516
517 case EfiBadgingDisplayAttributeCenterRight:
518 DestX = (SizeOfX - Width - CoordinateX);
519 DestY = (SizeOfY - Height) / 2;
520 break;
521
522 case EfiBadgingDisplayAttributeRightBottom:
523 DestX = (SizeOfX - Width - CoordinateX);
524 DestY = (SizeOfY - Height - CoordinateY);
525 break;
526
527 case EfiBadgingDisplayAttributeCenterBottom:
528 DestX = (SizeOfX - Width) / 2;
529 DestY = (SizeOfY - Height - CoordinateY);
530 break;
531
532 case EfiBadgingDisplayAttributeLeftBottom:
533 DestX = CoordinateX;
534 DestY = (SizeOfY - Height - CoordinateY);
535 break;
536
537 case EfiBadgingDisplayAttributeCenterLeft:
538 DestX = CoordinateX;
539 DestY = (SizeOfY - Height) / 2;
540 break;
541
542 case EfiBadgingDisplayAttributeCenter:
543 DestX = (SizeOfX - Width) / 2;
544 DestY = (SizeOfY - Height) / 2;
545 break;
546
547 default:
548 DestX = CoordinateX;
549 DestY = CoordinateY;
550 break;
551 }
552
553 if ((DestX >= 0) && (DestY >= 0)) {
554 if (GraphicsOutput != NULL) {
555 Status = GraphicsOutput->Blt (
556 GraphicsOutput,
557 Blt,
558 EfiBltBufferToVideo,
559 0,
560 0,
561 (UINTN) DestX,
562 (UINTN) DestY,
563 Width,
564 Height,
565 Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
566 );
567 } else {
568 Status = UgaDraw->Blt (
569 UgaDraw,
570 (EFI_UGA_PIXEL *) Blt,
571 EfiUgaBltBufferToVideo,
572 0,
573 0,
574 (UINTN) DestX,
575 (UINTN) DestY,
576 Width,
577 Height,
578 Width * sizeof (EFI_UGA_PIXEL)
579 );
580 }
581 }
582
583 gBS->FreePool (ImageData);
584 gBS->FreePool (Blt);
585
586 if (Badging == NULL) {
587 break;
588 }
589 }
590
591 return Status;
592 }
593
594
595 EFI_STATUS
596 DisableQuietBoot (
597 VOID
598 )
599 /*++
600
601 Routine Description:
602
603 Use Console Control to turn on GOP/UGA based Simple Text Out consoles. The GOP/UGA
604 Simple Text Out screens will now be synced up with all non GOP/UGA output devices
605
606 Arguments:
607
608 NONE
609
610 Returns:
611
612 EFI_SUCCESS - GOP/UGA devices are back in text mode and synced up.
613 EFI_UNSUPPORTED - Logo not found
614
615 --*/
616 {
617 EFI_STATUS Status;
618 EFI_CONSOLE_CONTROL_PROTOCOL *ConsoleControl;
619
620 Status = gBS->LocateProtocol (&gEfiConsoleControlProtocolGuid, NULL, (VOID **) &ConsoleControl);
621 if (EFI_ERROR (Status)) {
622 return EFI_UNSUPPORTED;
623 }
624
625 return ConsoleControl->SetMode (ConsoleControl, EfiConsoleControlScreenText);
626 }