]> git.proxmox.com Git - mirror_edk2.git/blame - IntelFrameworkModulePkg/Library/GenericBdsLib/BdsConsole.c
Explicit to judge whether Index is out of boundary.
[mirror_edk2.git] / IntelFrameworkModulePkg / Library / GenericBdsLib / BdsConsole.c
CommitLineData
5c08e117 1/** @file\r
2 BDS Lib functions which contain all the code to connect console device\r
3\r
5d7c1609 4Copyright (c) 2004 - 2009, Intel Corporation. <BR>\r
5c08e117 5All rights reserved. This program and the accompanying materials\r
6are licensed and made available under the terms and conditions of the BSD License\r
7which accompanies this distribution. The full text of the license may be found at\r
8http://opensource.org/licenses/bsd-license.php\r
9\r
10THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12\r
13**/\r
14\r
15#include "InternalBdsLib.h"\r
0682583a 16#include "Bmp.h"\r
5c08e117 17\r
18/**\r
19 Check if we need to save the EFI variable with "ConVarName" as name\r
20 as NV type\r
775a9b19 21 If ConVarName is NULL, then ASSERT().\r
22 \r
5c08e117 23 @param ConVarName The name of the EFI variable.\r
24\r
25 @retval TRUE Set the EFI variable as NV type.\r
26 @retval FALSE EFI variable as NV type can be set NonNV.\r
27**/\r
28BOOLEAN\r
29IsNvNeed (\r
30 IN CHAR16 *ConVarName\r
31 )\r
32{\r
33 CHAR16 *Ptr;\r
34\r
775a9b19 35 ASSERT (ConVarName != NULL);\r
36 \r
5c08e117 37 Ptr = ConVarName;\r
38\r
39 //\r
40 // If the variable includes "Dev" at last, we consider\r
41 // it does not support NV attribute.\r
42 //\r
43 while (*Ptr != L'\0') {\r
44 Ptr++;\r
45 }\r
46\r
f0a3b1a2 47 if ((((UINTN)Ptr - (UINTN)ConVarName) / sizeof (CHAR16)) <= 3) {\r
48 return TRUE;\r
49 }\r
50 \r
5c08e117 51 if ((*(Ptr - 3) == 'D') && (*(Ptr - 2) == 'e') && (*(Ptr - 1) == 'v')) {\r
52 return FALSE;\r
53 } else {\r
54 return TRUE;\r
55 }\r
56}\r
57\r
dad60833 58/**\r
59 Fill console handle in System Table if there are no valid console handle in.\r
60\r
61 Firstly, check the validation of console handle in System Table. If it is invalid,\r
62 update it by the first console device handle from EFI console variable. \r
63\r
64 @param VarName The name of the EFI console variable.\r
65 @param ConsoleGuid Specified Console protocol GUID.\r
66 @param ConsoleHandle On IN, console handle in System Table to be checked. \r
67 On OUT, new console hanlde in system table.\r
68 @param ProtocolInterface On IN, console protocol on console handle in System Table to be checked. \r
69 On OUT, new console protocol on new console hanlde in system table.\r
406ddad3 70\r
71 @retval TRUE System Table has been updated.\r
72 @retval FALSE System Table hasn't been updated.\r
73\r
dad60833 74**/\r
406ddad3 75BOOLEAN \r
dad60833 76UpdateSystemTableConsole (\r
77 IN CHAR16 *VarName,\r
78 IN EFI_GUID *ConsoleGuid,\r
79 IN OUT EFI_HANDLE *ConsoleHandle,\r
80 IN OUT VOID **ProtocolInterface\r
81 )\r
82{\r
83 EFI_STATUS Status;\r
84 UINTN DevicePathSize;\r
85 EFI_DEVICE_PATH_PROTOCOL *FullDevicePath;\r
86 EFI_DEVICE_PATH_PROTOCOL *VarConsole;\r
87 EFI_DEVICE_PATH_PROTOCOL *Instance;\r
88 VOID *Interface;\r
89 EFI_HANDLE NewHandle;\r
90\r
91 ASSERT (VarName != NULL);\r
92 ASSERT (ConsoleHandle != NULL);\r
93 ASSERT (ConsoleGuid != NULL);\r
94 ASSERT (ProtocolInterface != NULL);\r
95\r
96 if (*ConsoleHandle != NULL) {\r
97 Status = gBS->HandleProtocol (\r
98 *ConsoleHandle,\r
99 ConsoleGuid,\r
100 &Interface\r
101 );\r
102 if (Status == EFI_SUCCESS && Interface == *ProtocolInterface) {\r
103 //\r
104 // If ConsoleHandle is valid and console protocol on this handle also\r
105 // also matched, just return.\r
106 //\r
406ddad3 107 return FALSE;\r
dad60833 108 }\r
109 }\r
110 \r
111 //\r
112 // Get all possible consoles device path from EFI variable\r
113 //\r
114 VarConsole = BdsLibGetVariableAndSize (\r
115 VarName,\r
116 &gEfiGlobalVariableGuid,\r
117 &DevicePathSize\r
118 );\r
119 if (VarConsole == NULL) {\r
120 //\r
121 // If there is no any console device, just return.\r
122 //\r
406ddad3 123 return FALSE;\r
dad60833 124 }\r
125\r
126 FullDevicePath = VarConsole;\r
127\r
128 do {\r
129 //\r
130 // Check every instance of the console variable\r
131 //\r
132 Instance = GetNextDevicePathInstance (&VarConsole, &DevicePathSize);\r
133 if (Instance == NULL) {\r
134 FreePool (FullDevicePath);\r
135 ASSERT (FALSE);\r
136 }\r
137 \r
138 //\r
139 // Find console device handle by device path instance\r
140 //\r
141 Status = gBS->LocateDevicePath (\r
142 ConsoleGuid,\r
143 &Instance,\r
144 &NewHandle\r
145 );\r
146 if (!EFI_ERROR (Status)) {\r
147 //\r
148 // Get the console protocol on this console device handle\r
149 //\r
150 Status = gBS->HandleProtocol (\r
151 NewHandle,\r
152 ConsoleGuid,\r
153 &Interface\r
154 );\r
155 if (!EFI_ERROR (Status)) {\r
156 //\r
157 // Update new console handle in System Table.\r
158 //\r
159 *ConsoleHandle = NewHandle;\r
160 *ProtocolInterface = Interface;\r
406ddad3 161 return TRUE;\r
dad60833 162 }\r
163 }\r
164\r
165 } while (Instance != NULL);\r
166\r
167 //\r
168 // No any available console devcie found.\r
169 //\r
406ddad3 170 return FALSE;\r
dad60833 171}\r
172\r
5c08e117 173/**\r
174 This function update console variable based on ConVarName, it can\r
175 add or remove one specific console device path from the variable\r
176\r
177 @param ConVarName Console related variable name, ConIn, ConOut,\r
178 ErrOut.\r
179 @param CustomizedConDevicePath The console device path which will be added to\r
180 the console variable ConVarName, this parameter\r
181 can not be multi-instance.\r
182 @param ExclusiveDevicePath The console device path which will be removed\r
183 from the console variable ConVarName, this\r
184 parameter can not be multi-instance.\r
185\r
186 @retval EFI_UNSUPPORTED The added device path is same to the removed one.\r
187 @retval EFI_SUCCESS Success add or remove the device path from the\r
188 console variable.\r
189\r
190**/\r
191EFI_STATUS\r
192EFIAPI\r
193BdsLibUpdateConsoleVariable (\r
194 IN CHAR16 *ConVarName,\r
195 IN EFI_DEVICE_PATH_PROTOCOL *CustomizedConDevicePath,\r
196 IN EFI_DEVICE_PATH_PROTOCOL *ExclusiveDevicePath\r
197 )\r
198{\r
199 EFI_DEVICE_PATH_PROTOCOL *VarConsole;\r
200 UINTN DevicePathSize;\r
201 EFI_DEVICE_PATH_PROTOCOL *NewDevicePath;\r
202 EFI_DEVICE_PATH_PROTOCOL *TempNewDevicePath;\r
203 UINT32 Attributes;\r
204\r
205 VarConsole = NULL;\r
206 DevicePathSize = 0;\r
207\r
208 //\r
209 // Notes: check the device path point, here should check\r
210 // with compare memory\r
211 //\r
212 if (CustomizedConDevicePath == ExclusiveDevicePath) {\r
213 return EFI_UNSUPPORTED;\r
214 }\r
215 //\r
216 // Delete the ExclusiveDevicePath from current default console\r
217 //\r
218 VarConsole = BdsLibGetVariableAndSize (\r
219 ConVarName,\r
220 &gEfiGlobalVariableGuid,\r
221 &DevicePathSize\r
222 );\r
223\r
224 //\r
225 // Initialize NewDevicePath\r
226 //\r
227 NewDevicePath = VarConsole;\r
228\r
229 //\r
230 // If ExclusiveDevicePath is even the part of the instance in VarConsole, delete it.\r
231 // In the end, NewDevicePath is the final device path.\r
232 //\r
233 if (ExclusiveDevicePath != NULL && VarConsole != NULL) {\r
234 NewDevicePath = BdsLibDelPartMatchInstance (VarConsole, ExclusiveDevicePath);\r
235 }\r
236 //\r
237 // Try to append customized device path to NewDevicePath.\r
238 //\r
239 if (CustomizedConDevicePath != NULL) {\r
240 if (!BdsLibMatchDevicePaths (NewDevicePath, CustomizedConDevicePath)) {\r
241 //\r
242 // Check if there is part of CustomizedConDevicePath in NewDevicePath, delete it.\r
243 //\r
244 NewDevicePath = BdsLibDelPartMatchInstance (NewDevicePath, CustomizedConDevicePath);\r
245 //\r
246 // In the first check, the default console variable will be _ModuleEntryPoint,\r
247 // just append current customized device path\r
248 //\r
249 TempNewDevicePath = NewDevicePath;\r
250 NewDevicePath = AppendDevicePathInstance (NewDevicePath, CustomizedConDevicePath);\r
251 if (TempNewDevicePath != NULL) {\r
252 FreePool(TempNewDevicePath);\r
253 }\r
254 }\r
255 }\r
256\r
257 //\r
258 // The attribute for ConInDev, ConOutDev and ErrOutDev does not include NV.\r
259 //\r
260 if (IsNvNeed(ConVarName)) {\r
261 //\r
262 // ConVarName has NV attribute.\r
263 //\r
264 Attributes = EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE;\r
265 } else {\r
266 //\r
267 // ConVarName does not have NV attribute.\r
268 //\r
269 Attributes = EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS;\r
270 }\r
271\r
272 //\r
273 // Finally, Update the variable of the default console by NewDevicePath\r
274 //\r
275 gRT->SetVariable (\r
276 ConVarName,\r
277 &gEfiGlobalVariableGuid,\r
278 Attributes,\r
279 GetDevicePathSize (NewDevicePath),\r
280 NewDevicePath\r
281 );\r
282\r
283 if (VarConsole == NewDevicePath) {\r
284 if (VarConsole != NULL) {\r
285 FreePool(VarConsole);\r
286 }\r
287 } else {\r
288 if (VarConsole != NULL) {\r
289 FreePool(VarConsole);\r
290 }\r
291 if (NewDevicePath != NULL) {\r
292 FreePool(NewDevicePath);\r
293 }\r
294 }\r
295\r
296 return EFI_SUCCESS;\r
297\r
298}\r
299\r
300\r
301/**\r
302 Connect the console device base on the variable ConVarName, if\r
303 device path of the ConVarName is multi-instance device path, if\r
304 anyone of the instances is connected success, then this function\r
305 will return success.\r
306\r
307 @param ConVarName Console related variable name, ConIn, ConOut,\r
308 ErrOut.\r
309\r
310 @retval EFI_NOT_FOUND There is not any console devices connected\r
311 success\r
312 @retval EFI_SUCCESS Success connect any one instance of the console\r
313 device path base on the variable ConVarName.\r
314\r
315**/\r
316EFI_STATUS\r
317EFIAPI\r
318BdsLibConnectConsoleVariable (\r
319 IN CHAR16 *ConVarName\r
320 )\r
321{\r
322 EFI_STATUS Status;\r
323 EFI_DEVICE_PATH_PROTOCOL *StartDevicePath;\r
324 UINTN VariableSize;\r
325 EFI_DEVICE_PATH_PROTOCOL *Instance;\r
326 EFI_DEVICE_PATH_PROTOCOL *Next;\r
327 EFI_DEVICE_PATH_PROTOCOL *CopyOfDevicePath;\r
328 UINTN Size;\r
329 BOOLEAN DeviceExist;\r
330\r
331 Status = EFI_SUCCESS;\r
332 DeviceExist = FALSE;\r
333\r
334 //\r
335 // Check if the console variable exist\r
336 //\r
337 StartDevicePath = BdsLibGetVariableAndSize (\r
338 ConVarName,\r
339 &gEfiGlobalVariableGuid,\r
340 &VariableSize\r
341 );\r
342 if (StartDevicePath == NULL) {\r
343 return EFI_UNSUPPORTED;\r
344 }\r
345\r
346 CopyOfDevicePath = StartDevicePath;\r
347 do {\r
348 //\r
349 // Check every instance of the console variable\r
350 //\r
351 Instance = GetNextDevicePathInstance (&CopyOfDevicePath, &Size);\r
352 if (Instance == NULL) {\r
353 FreePool (StartDevicePath);\r
354 return EFI_UNSUPPORTED;\r
355 }\r
356 \r
357 Next = Instance;\r
358 while (!IsDevicePathEndType (Next)) {\r
359 Next = NextDevicePathNode (Next);\r
360 }\r
361\r
362 SetDevicePathEndNode (Next);\r
363 //\r
364 // Check USB1.1 console\r
365 //\r
366 if ((DevicePathType (Instance) == MESSAGING_DEVICE_PATH) &&\r
367 ((DevicePathSubType (Instance) == MSG_USB_CLASS_DP)\r
368 || (DevicePathSubType (Instance) == MSG_USB_WWID_DP)\r
369 )) {\r
370 //\r
371 // Check the Usb console in Usb2.0 bus firstly, then Usb1.1 bus\r
372 //\r
373 Status = BdsLibConnectUsbDevByShortFormDP (PCI_CLASSC_PI_EHCI, Instance);\r
374 if (!EFI_ERROR (Status)) {\r
375 DeviceExist = TRUE;\r
376 }\r
377\r
378 Status = BdsLibConnectUsbDevByShortFormDP (PCI_CLASSC_PI_UHCI, Instance);\r
379 if (!EFI_ERROR (Status)) {\r
380 DeviceExist = TRUE;\r
381 }\r
382 } else {\r
383 //\r
384 // Connect the instance device path\r
385 //\r
386 Status = BdsLibConnectDevicePath (Instance);\r
387 if (EFI_ERROR (Status)) {\r
388 //\r
389 // Delete the instance from the console varialbe\r
390 //\r
391 BdsLibUpdateConsoleVariable (ConVarName, NULL, Instance);\r
392 } else {\r
393 DeviceExist = TRUE;\r
394 }\r
395 }\r
396 FreePool(Instance);\r
397 } while (CopyOfDevicePath != NULL);\r
398\r
399 FreePool (StartDevicePath);\r
400\r
401 if (!DeviceExist) {\r
402 return EFI_NOT_FOUND;\r
403 }\r
404\r
405 return EFI_SUCCESS;\r
406}\r
407\r
408\r
409/**\r
410 This function will search every simpletext device in current system,\r
411 and make every simpletext device as pertantial console device.\r
412\r
413**/\r
414VOID\r
415EFIAPI\r
416BdsLibConnectAllConsoles (\r
417 VOID\r
418 )\r
419{\r
420 UINTN Index;\r
421 EFI_DEVICE_PATH_PROTOCOL *ConDevicePath;\r
422 UINTN HandleCount;\r
423 EFI_HANDLE *HandleBuffer;\r
424\r
425 Index = 0;\r
426 HandleCount = 0;\r
427 HandleBuffer = NULL;\r
428 ConDevicePath = NULL;\r
429\r
430 //\r
431 // Update all the console variables\r
432 //\r
433 gBS->LocateHandleBuffer (\r
434 ByProtocol,\r
435 &gEfiSimpleTextInProtocolGuid,\r
436 NULL,\r
437 &HandleCount,\r
438 &HandleBuffer\r
439 );\r
440\r
441 for (Index = 0; Index < HandleCount; Index++) {\r
442 gBS->HandleProtocol (\r
443 HandleBuffer[Index],\r
444 &gEfiDevicePathProtocolGuid,\r
445 (VOID **) &ConDevicePath\r
446 );\r
447 BdsLibUpdateConsoleVariable (L"ConIn", ConDevicePath, NULL);\r
448 }\r
449\r
450 if (HandleBuffer != NULL) {\r
451 FreePool(HandleBuffer);\r
452 HandleBuffer = NULL;\r
453 }\r
454\r
455 gBS->LocateHandleBuffer (\r
456 ByProtocol,\r
457 &gEfiSimpleTextOutProtocolGuid,\r
458 NULL,\r
459 &HandleCount,\r
460 &HandleBuffer\r
461 );\r
462 for (Index = 0; Index < HandleCount; Index++) {\r
463 gBS->HandleProtocol (\r
464 HandleBuffer[Index],\r
465 &gEfiDevicePathProtocolGuid,\r
466 (VOID **) &ConDevicePath\r
467 );\r
468 BdsLibUpdateConsoleVariable (L"ConOut", ConDevicePath, NULL);\r
469 BdsLibUpdateConsoleVariable (L"ErrOut", ConDevicePath, NULL);\r
470 }\r
471\r
472 if (HandleBuffer != NULL) {\r
473 FreePool(HandleBuffer);\r
474 }\r
475\r
476 //\r
477 // Connect all console variables\r
478 //\r
479 BdsLibConnectAllDefaultConsoles ();\r
480\r
481}\r
482\r
483/**\r
484 This function will connect console device base on the console\r
485 device variable ConIn, ConOut and ErrOut.\r
486\r
487 @retval EFI_SUCCESS At least one of the ConIn and ConOut device have\r
488 been connected success.\r
489 @retval EFI_STATUS Return the status of BdsLibConnectConsoleVariable ().\r
490\r
491**/\r
492EFI_STATUS\r
493EFIAPI\r
494BdsLibConnectAllDefaultConsoles (\r
495 VOID\r
496 )\r
497{\r
498 EFI_STATUS Status;\r
406ddad3 499 BOOLEAN SystemTableUpdated;\r
5c08e117 500\r
501 //\r
502 // Connect all default console variables\r
503 //\r
504\r
505 //\r
506 // It seems impossible not to have any ConOut device on platform,\r
507 // so we check the status here.\r
508 //\r
509 Status = BdsLibConnectConsoleVariable (L"ConOut");\r
510 if (EFI_ERROR (Status)) {\r
511 return Status;\r
512 }\r
513\r
514 //\r
515 // Insert the performance probe for Console Out\r
516 //\r
517 PERF_START (NULL, "ConOut", "BDS", 1);\r
518 PERF_END (NULL, "ConOut", "BDS", 0);\r
519\r
520 //\r
521 // Because possibly the platform is legacy free, in such case,\r
522 // ConIn devices (Serial Port and PS2 Keyboard ) does not exist,\r
523 // so we need not check the status.\r
524 //\r
525 BdsLibConnectConsoleVariable (L"ConIn");\r
526\r
527 //\r
528 // The _ModuleEntryPoint err out var is legal.\r
529 //\r
530 BdsLibConnectConsoleVariable (L"ErrOut");\r
531\r
406ddad3 532 SystemTableUpdated = FALSE;\r
dad60833 533 //\r
534 // Fill console handles in System Table if no console device assignd.\r
535 //\r
406ddad3 536 if (UpdateSystemTableConsole (L"ConIn", &gEfiSimpleTextInProtocolGuid, &gST->ConsoleInHandle, (VOID **) &gST->ConIn)) {\r
537 SystemTableUpdated = TRUE;\r
538 }\r
539 if (UpdateSystemTableConsole (L"ConOut", &gEfiSimpleTextOutProtocolGuid, &gST->ConsoleOutHandle, (VOID **) &gST->ConOut)) {\r
540 SystemTableUpdated = TRUE;\r
541 }\r
542 if (UpdateSystemTableConsole (L"ErrOut", &gEfiSimpleTextOutProtocolGuid, &gST->StandardErrorHandle, (VOID **) &gST->StdErr)) {\r
543 SystemTableUpdated = TRUE;\r
544 }\r
545\r
546 if (SystemTableUpdated) {\r
547 //\r
548 // Update the CRC32 in the EFI System Table header\r
549 //\r
550 gST->Hdr.CRC32 = 0;\r
551 gBS->CalculateCrc32 (\r
552 (UINT8 *) &gST->Hdr,\r
553 gST->Hdr.HeaderSize,\r
554 &gST->Hdr.CRC32\r
555 );\r
556 }\r
dad60833 557\r
5c08e117 558 return EFI_SUCCESS;\r
559\r
560}\r
561\r
562/**\r
563 Convert a *.BMP graphics image to a GOP blt buffer. If a NULL Blt buffer\r
564 is passed in a GopBlt buffer will be allocated by this routine. If a GopBlt\r
565 buffer is passed in it will be used if it is big enough.\r
566\r
567 @param BmpImage Pointer to BMP file\r
568 @param BmpImageSize Number of bytes in BmpImage\r
569 @param GopBlt Buffer containing GOP version of BmpImage.\r
570 @param GopBltSize Size of GopBlt in bytes.\r
571 @param PixelHeight Height of GopBlt/BmpImage in pixels\r
572 @param PixelWidth Width of GopBlt/BmpImage in pixels\r
573\r
574 @retval EFI_SUCCESS GopBlt and GopBltSize are returned.\r
575 @retval EFI_UNSUPPORTED BmpImage is not a valid *.BMP image\r
576 @retval EFI_BUFFER_TOO_SMALL The passed in GopBlt buffer is not big enough.\r
577 GopBltSize will contain the required size.\r
578 @retval EFI_OUT_OF_RESOURCES No enough buffer to allocate.\r
579\r
580**/\r
581EFI_STATUS\r
582ConvertBmpToGopBlt (\r
583 IN VOID *BmpImage,\r
584 IN UINTN BmpImageSize,\r
585 IN OUT VOID **GopBlt,\r
586 IN OUT UINTN *GopBltSize,\r
587 OUT UINTN *PixelHeight,\r
588 OUT UINTN *PixelWidth\r
589 )\r
590{\r
591 UINT8 *Image;\r
592 UINT8 *ImageHeader;\r
593 BMP_IMAGE_HEADER *BmpHeader;\r
594 BMP_COLOR_MAP *BmpColorMap;\r
595 EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer;\r
596 EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Blt;\r
88f2bdb5 597 UINT64 BltBufferSize;\r
5c08e117 598 UINTN Index;\r
599 UINTN Height;\r
600 UINTN Width;\r
601 UINTN ImageIndex;\r
602 BOOLEAN IsAllocated;\r
603\r
604 BmpHeader = (BMP_IMAGE_HEADER *) BmpImage;\r
605\r
606 if (BmpHeader->CharB != 'B' || BmpHeader->CharM != 'M') {\r
607 return EFI_UNSUPPORTED;\r
608 }\r
609\r
610 //\r
611 // Doesn't support compress.\r
612 //\r
613 if (BmpHeader->CompressionType != 0) {\r
614 return EFI_UNSUPPORTED;\r
615 }\r
616\r
617 //\r
618 // Calculate Color Map offset in the image.\r
619 //\r
620 Image = BmpImage;\r
621 BmpColorMap = (BMP_COLOR_MAP *) (Image + sizeof (BMP_IMAGE_HEADER));\r
622\r
623 //\r
624 // Calculate graphics image data address in the image\r
625 //\r
626 Image = ((UINT8 *) BmpImage) + BmpHeader->ImageOffset;\r
627 ImageHeader = Image;\r
628\r
629 //\r
630 // Calculate the BltBuffer needed size.\r
631 //\r
632 BltBufferSize = BmpHeader->PixelWidth * BmpHeader->PixelHeight * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);\r
88f2bdb5 633 if (BltBufferSize >= SIZE_4GB) {\r
634 //\r
635 // If the BMP resolution is too large\r
636 //\r
637 return EFI_UNSUPPORTED;\r
638 }\r
639 \r
5c08e117 640 IsAllocated = FALSE;\r
641 if (*GopBlt == NULL) {\r
642 //\r
643 // GopBlt is not allocated by caller.\r
644 //\r
88f2bdb5 645 *GopBltSize = (UINTN) BltBufferSize;\r
5c08e117 646 *GopBlt = AllocatePool (*GopBltSize);\r
647 IsAllocated = TRUE;\r
648 if (*GopBlt == NULL) {\r
649 return EFI_OUT_OF_RESOURCES;\r
650 }\r
651 } else {\r
652 //\r
653 // GopBlt has been allocated by caller.\r
654 //\r
2bf3421a 655 if (*GopBltSize < (UINTN) BltBufferSize) {\r
88f2bdb5 656 *GopBltSize = (UINTN) BltBufferSize;\r
5c08e117 657 return EFI_BUFFER_TOO_SMALL;\r
658 }\r
659 }\r
660\r
661 *PixelWidth = BmpHeader->PixelWidth;\r
662 *PixelHeight = BmpHeader->PixelHeight;\r
663\r
664 //\r
665 // Convert image from BMP to Blt buffer format\r
666 //\r
667 BltBuffer = *GopBlt;\r
668 for (Height = 0; Height < BmpHeader->PixelHeight; Height++) {\r
669 Blt = &BltBuffer[(BmpHeader->PixelHeight - Height - 1) * BmpHeader->PixelWidth];\r
670 for (Width = 0; Width < BmpHeader->PixelWidth; Width++, Image++, Blt++) {\r
671 switch (BmpHeader->BitPerPixel) {\r
672 case 1:\r
673 //\r
674 // Convert 1-bit (2 colors) BMP to 24-bit color\r
675 //\r
676 for (Index = 0; Index < 8 && Width < BmpHeader->PixelWidth; Index++) {\r
677 Blt->Red = BmpColorMap[((*Image) >> (7 - Index)) & 0x1].Red;\r
678 Blt->Green = BmpColorMap[((*Image) >> (7 - Index)) & 0x1].Green;\r
679 Blt->Blue = BmpColorMap[((*Image) >> (7 - Index)) & 0x1].Blue;\r
680 Blt++;\r
681 Width++;\r
682 }\r
683\r
684 Blt--;\r
685 Width--;\r
686 break;\r
687\r
688 case 4:\r
689 //\r
690 // Convert 4-bit (16 colors) BMP Palette to 24-bit color\r
691 //\r
692 Index = (*Image) >> 4;\r
693 Blt->Red = BmpColorMap[Index].Red;\r
694 Blt->Green = BmpColorMap[Index].Green;\r
695 Blt->Blue = BmpColorMap[Index].Blue;\r
696 if (Width < (BmpHeader->PixelWidth - 1)) {\r
697 Blt++;\r
698 Width++;\r
699 Index = (*Image) & 0x0f;\r
700 Blt->Red = BmpColorMap[Index].Red;\r
701 Blt->Green = BmpColorMap[Index].Green;\r
702 Blt->Blue = BmpColorMap[Index].Blue;\r
703 }\r
704 break;\r
705\r
706 case 8:\r
707 //\r
708 // Convert 8-bit (256 colors) BMP Palette to 24-bit color\r
709 //\r
710 Blt->Red = BmpColorMap[*Image].Red;\r
711 Blt->Green = BmpColorMap[*Image].Green;\r
712 Blt->Blue = BmpColorMap[*Image].Blue;\r
713 break;\r
714\r
715 case 24:\r
716 //\r
717 // It is 24-bit BMP.\r
718 //\r
719 Blt->Blue = *Image++;\r
720 Blt->Green = *Image++;\r
721 Blt->Red = *Image;\r
722 break;\r
723\r
724 default:\r
725 //\r
726 // Other bit format BMP is not supported.\r
727 //\r
728 if (IsAllocated) {\r
729 FreePool (*GopBlt);\r
730 *GopBlt = NULL;\r
731 }\r
732 return EFI_UNSUPPORTED;\r
733 break;\r
734 };\r
735\r
736 }\r
737\r
738 ImageIndex = (UINTN) (Image - ImageHeader);\r
739 if ((ImageIndex % 4) != 0) {\r
740 //\r
741 // Bmp Image starts each row on a 32-bit boundary!\r
742 //\r
743 Image = Image + (4 - (ImageIndex % 4));\r
744 }\r
745 }\r
746\r
747 return EFI_SUCCESS;\r
748}\r
749\r
750\r
751/**\r
752 Use Console Control Protocol to lock the Console In Spliter virtual handle.\r
753 This is the ConInHandle and ConIn handle in the EFI system table. All key\r
754 presses will be ignored until the Password is typed in. The only way to\r
755 disable the password is to type it in to a ConIn device.\r
756\r
757 @param Password Password used to lock ConIn device.\r
758\r
759 @retval EFI_SUCCESS lock the Console In Spliter virtual handle successfully.\r
760 @retval EFI_UNSUPPORTED Password not found\r
761\r
762**/\r
763EFI_STATUS\r
764EFIAPI\r
765LockKeyboards (\r
766 IN CHAR16 *Password\r
767 )\r
768{\r
5c08e117 769 return EFI_UNSUPPORTED;\r
5c08e117 770}\r
771\r
772\r
773/**\r
774 Use Console Control to turn off UGA based Simple Text Out consoles from going\r
775 to the UGA device. Put up LogoFile on every UGA device that is a console\r
776\r
777 @param[in] LogoFile File name of logo to display on the center of the screen.\r
778\r
779 @retval EFI_SUCCESS ConsoleControl has been flipped to graphics and logo displayed.\r
780 @retval EFI_UNSUPPORTED Logo not found\r
781\r
782**/\r
783EFI_STATUS\r
784EFIAPI\r
785EnableQuietBoot (\r
786 IN EFI_GUID *LogoFile\r
787 )\r
788{\r
789 EFI_STATUS Status;\r
5c08e117 790 EFI_OEM_BADGING_PROTOCOL *Badging;\r
791 UINT32 SizeOfX;\r
792 UINT32 SizeOfY;\r
793 INTN DestX;\r
794 INTN DestY;\r
795 UINT8 *ImageData;\r
796 UINTN ImageSize;\r
797 UINTN BltSize;\r
798 UINT32 Instance;\r
799 EFI_BADGING_FORMAT Format;\r
800 EFI_BADGING_DISPLAY_ATTRIBUTE Attribute;\r
801 UINTN CoordinateX;\r
802 UINTN CoordinateY;\r
803 UINTN Height;\r
804 UINTN Width;\r
805 EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Blt;\r
806 EFI_UGA_DRAW_PROTOCOL *UgaDraw;\r
807 UINT32 ColorDepth;\r
808 UINT32 RefreshRate;\r
809 EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;\r
810\r
5c08e117 811 UgaDraw = NULL;\r
812 //\r
813 // Try to open GOP first\r
814 //\r
815 Status = gBS->HandleProtocol (gST->ConsoleOutHandle, &gEfiGraphicsOutputProtocolGuid, (VOID **) &GraphicsOutput);\r
816 if (EFI_ERROR (Status) && FeaturePcdGet (PcdUgaConsumeSupport)) {\r
817 GraphicsOutput = NULL;\r
818 //\r
819 // Open GOP failed, try to open UGA\r
820 //\r
821 Status = gBS->HandleProtocol (gST->ConsoleOutHandle, &gEfiUgaDrawProtocolGuid, (VOID **) &UgaDraw);\r
822 }\r
823 if (EFI_ERROR (Status)) {\r
824 return EFI_UNSUPPORTED;\r
825 }\r
826\r
5c08e117 827 //\r
5d7c1609 828 // Erase Cursor from screen\r
5c08e117 829 //\r
5d7c1609 830 gST->ConOut->EnableCursor (gST->ConOut, FALSE);\r
831\r
832 Badging = NULL;\r
833 Status = gBS->LocateProtocol (&gEfiOEMBadgingProtocolGuid, NULL, (VOID **) &Badging);\r
5c08e117 834\r
835 if (GraphicsOutput != NULL) {\r
836 SizeOfX = GraphicsOutput->Mode->Info->HorizontalResolution;\r
837 SizeOfY = GraphicsOutput->Mode->Info->VerticalResolution;\r
838\r
839 } else if (UgaDraw != NULL && FeaturePcdGet (PcdUgaConsumeSupport)) {\r
840 Status = UgaDraw->GetMode (UgaDraw, &SizeOfX, &SizeOfY, &ColorDepth, &RefreshRate);\r
841 if (EFI_ERROR (Status)) {\r
842 return EFI_UNSUPPORTED;\r
843 }\r
844 } else {\r
845 return EFI_UNSUPPORTED;\r
846 }\r
847\r
848 Instance = 0;\r
849 while (1) {\r
850 ImageData = NULL;\r
851 ImageSize = 0;\r
852\r
853 if (Badging != NULL) {\r
854 //\r
855 // Get image from OEMBadging protocol.\r
856 //\r
857 Status = Badging->GetImage (\r
858 Badging,\r
859 &Instance,\r
860 &Format,\r
861 &ImageData,\r
862 &ImageSize,\r
863 &Attribute,\r
864 &CoordinateX,\r
865 &CoordinateY\r
866 );\r
867 if (EFI_ERROR (Status)) {\r
868 return Status;\r
869 }\r
870\r
871 //\r
872 // Currently only support BMP format.\r
873 //\r
874 if (Format != EfiBadgingFormatBMP) {\r
875 if (ImageData != NULL) {\r
876 FreePool (ImageData);\r
877 }\r
878 continue;\r
879 }\r
880 } else {\r
881 //\r
882 // Get the specified image from FV.\r
883 //\r
884 Status = GetSectionFromAnyFv (LogoFile, EFI_SECTION_RAW, 0, (VOID **) &ImageData, &ImageSize);\r
885 if (EFI_ERROR (Status)) {\r
886 return EFI_UNSUPPORTED;\r
887 }\r
888\r
889 CoordinateX = 0;\r
890 CoordinateY = 0;\r
891 Attribute = EfiBadgingDisplayAttributeCenter;\r
892 }\r
893\r
894 Blt = NULL;\r
895 Status = ConvertBmpToGopBlt (\r
896 ImageData,\r
897 ImageSize,\r
898 (VOID **) &Blt,\r
899 &BltSize,\r
900 &Height,\r
901 &Width\r
902 );\r
903 if (EFI_ERROR (Status)) {\r
904 FreePool (ImageData);\r
905\r
906 if (Badging == NULL) {\r
907 return Status;\r
908 } else {\r
909 continue;\r
910 }\r
911 }\r
912\r
913 //\r
914 // Calculate the display position according to Attribute.\r
915 //\r
916 switch (Attribute) {\r
917 case EfiBadgingDisplayAttributeLeftTop:\r
918 DestX = CoordinateX;\r
919 DestY = CoordinateY;\r
920 break;\r
921\r
922 case EfiBadgingDisplayAttributeCenterTop:\r
923 DestX = (SizeOfX - Width) / 2;\r
924 DestY = CoordinateY;\r
925 break;\r
926\r
927 case EfiBadgingDisplayAttributeRightTop:\r
928 DestX = (SizeOfX - Width - CoordinateX);\r
929 DestY = CoordinateY;;\r
930 break;\r
931\r
932 case EfiBadgingDisplayAttributeCenterRight:\r
933 DestX = (SizeOfX - Width - CoordinateX);\r
934 DestY = (SizeOfY - Height) / 2;\r
935 break;\r
936\r
937 case EfiBadgingDisplayAttributeRightBottom:\r
938 DestX = (SizeOfX - Width - CoordinateX);\r
939 DestY = (SizeOfY - Height - CoordinateY);\r
940 break;\r
941\r
942 case EfiBadgingDisplayAttributeCenterBottom:\r
943 DestX = (SizeOfX - Width) / 2;\r
944 DestY = (SizeOfY - Height - CoordinateY);\r
945 break;\r
946\r
947 case EfiBadgingDisplayAttributeLeftBottom:\r
948 DestX = CoordinateX;\r
949 DestY = (SizeOfY - Height - CoordinateY);\r
950 break;\r
951\r
952 case EfiBadgingDisplayAttributeCenterLeft:\r
953 DestX = CoordinateX;\r
954 DestY = (SizeOfY - Height) / 2;\r
955 break;\r
956\r
957 case EfiBadgingDisplayAttributeCenter:\r
958 DestX = (SizeOfX - Width) / 2;\r
959 DestY = (SizeOfY - Height) / 2;\r
960 break;\r
961\r
962 default:\r
963 DestX = CoordinateX;\r
964 DestY = CoordinateY;\r
965 break;\r
966 }\r
967\r
968 if ((DestX >= 0) && (DestY >= 0)) {\r
969 if (GraphicsOutput != NULL) {\r
970 Status = GraphicsOutput->Blt (\r
971 GraphicsOutput,\r
972 Blt,\r
973 EfiBltBufferToVideo,\r
974 0,\r
975 0,\r
976 (UINTN) DestX,\r
977 (UINTN) DestY,\r
978 Width,\r
979 Height,\r
980 Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)\r
981 );\r
982 } else if (UgaDraw != NULL && FeaturePcdGet (PcdUgaConsumeSupport)) {\r
983 Status = UgaDraw->Blt (\r
984 UgaDraw,\r
985 (EFI_UGA_PIXEL *) Blt,\r
986 EfiUgaBltBufferToVideo,\r
987 0,\r
988 0,\r
989 (UINTN) DestX,\r
990 (UINTN) DestY,\r
991 Width,\r
992 Height,\r
993 Width * sizeof (EFI_UGA_PIXEL)\r
994 );\r
995 } else {\r
996 Status = EFI_UNSUPPORTED;\r
997 }\r
998 }\r
999\r
1000 FreePool (ImageData);\r
1001\r
1002 if (Blt != NULL) {\r
1003 FreePool (Blt);\r
1004 }\r
1005\r
1006 if (Badging == NULL) {\r
1007 break;\r
1008 }\r
1009 }\r
1010\r
1011 return Status;\r
1012}\r
1013\r
1014/**\r
1015 Use Console Control to turn on UGA based Simple Text Out consoles. The UGA\r
1016 Simple Text Out screens will now be synced up with all non UGA output devices\r
1017\r
1018 @retval EFI_SUCCESS UGA devices are back in text mode and synced up.\r
1019\r
1020**/\r
1021EFI_STATUS\r
1022EFIAPI\r
1023DisableQuietBoot (\r
1024 VOID\r
1025 )\r
1026{\r
5c08e117 1027\r
1028 //\r
5d7c1609 1029 // Enable Cursor on Screen\r
5c08e117 1030 //\r
5d7c1609 1031 gST->ConOut->EnableCursor (gST->ConOut, TRUE);\r
1032 return EFI_SUCCESS;\r
5c08e117 1033}\r
1034\r