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