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