]> git.proxmox.com Git - mirror_edk2.git/blame - Nt32Pkg/Library/PlatformBootManagerLib/MemoryTest.c
Nt32Pkg: Keep boot behavior using new BDS almost same as that using old BDS
[mirror_edk2.git] / Nt32Pkg / Library / PlatformBootManagerLib / MemoryTest.c
CommitLineData
703da8b4
RN
1/** @file\r
2 Perform the platform memory test\r
3\r
4Copyright (c) 2004 - 2015, Intel Corporation. All rights reserved.<BR>\r
5This 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 "PlatformBootManager.h"\r
16\r
17EFI_HII_HANDLE gStringPackHandle = NULL;\r
18EFI_GUID mPlatformBootManagerStringPackGuid = {\r
19 0x154dd51, 0x9079, 0x4a10, { 0x89, 0x5c, 0x9c, 0x7, 0x72, 0x81, 0x57, 0x88 }\r
20 };\r
21// extern UINT8 BdsDxeStrings[];\r
22\r
23//\r
24// BDS Platform Functions\r
25//\r
26/**\r
27\r
28 Show progress bar with title above it. It only works in Graphics mode.\r
29\r
30\r
31 @param TitleForeground Foreground color for Title.\r
32 @param TitleBackground Background color for Title.\r
33 @param Title Title above progress bar.\r
34 @param ProgressColor Progress bar color.\r
35 @param Progress Progress (0-100)\r
36 @param PreviousValue The previous value of the progress.\r
37\r
38 @retval EFI_STATUS Success update the progress bar\r
39\r
40**/\r
41EFI_STATUS\r
42PlatformBootManagerShowProgress (\r
43 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL TitleForeground,\r
44 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL TitleBackground,\r
45 IN CHAR16 *Title,\r
46 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL ProgressColor,\r
47 IN UINTN Progress,\r
48 IN UINTN PreviousValue\r
49 )\r
50{\r
51 EFI_STATUS Status;\r
52 EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;\r
53 EFI_UGA_DRAW_PROTOCOL *UgaDraw;\r
54 UINT32 SizeOfX;\r
55 UINT32 SizeOfY;\r
56 UINT32 ColorDepth;\r
57 UINT32 RefreshRate;\r
58 EFI_GRAPHICS_OUTPUT_BLT_PIXEL Color;\r
59 UINTN BlockHeight;\r
60 UINTN BlockWidth;\r
61 UINTN BlockNum;\r
62 UINTN PosX;\r
63 UINTN PosY;\r
64 UINTN Index;\r
65\r
66 if (Progress > 100) {\r
67 return EFI_INVALID_PARAMETER;\r
68 }\r
69\r
70 UgaDraw = NULL;\r
71 Status = gBS->HandleProtocol (\r
72 gST->ConsoleOutHandle,\r
73 &gEfiGraphicsOutputProtocolGuid,\r
74 (VOID **) &GraphicsOutput\r
75 );\r
76 if (EFI_ERROR (Status) && FeaturePcdGet (PcdUgaConsumeSupport)) {\r
77 GraphicsOutput = NULL;\r
78\r
79 Status = gBS->HandleProtocol (\r
80 gST->ConsoleOutHandle,\r
81 &gEfiUgaDrawProtocolGuid,\r
82 (VOID **) &UgaDraw\r
83 );\r
84 }\r
85 if (EFI_ERROR (Status)) {\r
86 return EFI_UNSUPPORTED;\r
87 }\r
88\r
89 SizeOfX = 0;\r
90 SizeOfY = 0;\r
91 if (GraphicsOutput != NULL) {\r
92 SizeOfX = GraphicsOutput->Mode->Info->HorizontalResolution;\r
93 SizeOfY = GraphicsOutput->Mode->Info->VerticalResolution;\r
94 } else if (UgaDraw != NULL) {\r
95 Status = UgaDraw->GetMode (\r
96 UgaDraw,\r
97 &SizeOfX,\r
98 &SizeOfY,\r
99 &ColorDepth,\r
100 &RefreshRate\r
101 );\r
102 if (EFI_ERROR (Status)) {\r
103 return EFI_UNSUPPORTED;\r
104 }\r
105 } else {\r
106 return EFI_UNSUPPORTED;\r
107 }\r
108\r
109 BlockWidth = SizeOfX / 100;\r
110 BlockHeight = SizeOfY / 50;\r
111\r
112 BlockNum = Progress;\r
113\r
114 PosX = 0;\r
115 PosY = SizeOfY * 48 / 50;\r
116\r
117 if (BlockNum == 0) {\r
118 //\r
119 // Clear progress area\r
120 //\r
121 SetMem (&Color, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0x0);\r
122\r
123 if (GraphicsOutput != NULL) {\r
124 Status = GraphicsOutput->Blt (\r
125 GraphicsOutput,\r
126 &Color,\r
127 EfiBltVideoFill,\r
128 0,\r
129 0,\r
130 0,\r
131 PosY - EFI_GLYPH_HEIGHT - 1,\r
132 SizeOfX,\r
133 SizeOfY - (PosY - EFI_GLYPH_HEIGHT - 1),\r
134 SizeOfX * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)\r
135 );\r
136 } else if (FeaturePcdGet (PcdUgaConsumeSupport)) {\r
137 Status = UgaDraw->Blt (\r
138 UgaDraw,\r
139 (EFI_UGA_PIXEL *) &Color,\r
140 EfiUgaVideoFill,\r
141 0,\r
142 0,\r
143 0,\r
144 PosY - EFI_GLYPH_HEIGHT - 1,\r
145 SizeOfX,\r
146 SizeOfY - (PosY - EFI_GLYPH_HEIGHT - 1),\r
147 SizeOfX * sizeof (EFI_UGA_PIXEL)\r
148 );\r
149 } else {\r
150 return EFI_UNSUPPORTED;\r
151 }\r
152 }\r
153 //\r
154 // Show progress by drawing blocks\r
155 //\r
156 for (Index = PreviousValue; Index < BlockNum; Index++) {\r
157 PosX = Index * BlockWidth;\r
158 if (GraphicsOutput != NULL) {\r
159 Status = GraphicsOutput->Blt (\r
160 GraphicsOutput,\r
161 &ProgressColor,\r
162 EfiBltVideoFill,\r
163 0,\r
164 0,\r
165 PosX,\r
166 PosY,\r
167 BlockWidth - 1,\r
168 BlockHeight,\r
169 (BlockWidth) * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)\r
170 );\r
171 } else if (FeaturePcdGet (PcdUgaConsumeSupport)) {\r
172 Status = UgaDraw->Blt (\r
173 UgaDraw,\r
174 (EFI_UGA_PIXEL *) &ProgressColor,\r
175 EfiUgaVideoFill,\r
176 0,\r
177 0,\r
178 PosX,\r
179 PosY,\r
180 BlockWidth - 1,\r
181 BlockHeight,\r
182 (BlockWidth) * sizeof (EFI_UGA_PIXEL)\r
183 );\r
184 } else {\r
185 return EFI_UNSUPPORTED;\r
186 }\r
187 }\r
188\r
189 PrintXY (\r
190 (SizeOfX - StrLen (Title) * EFI_GLYPH_WIDTH) / 2,\r
191 PosY - EFI_GLYPH_HEIGHT - 1,\r
192 &TitleForeground,\r
193 &TitleBackground,\r
194 Title\r
195 );\r
196\r
197 return EFI_SUCCESS;\r
198}\r
199\r
200/**\r
201 Perform the memory test base on the memory test intensive level,\r
202 and update the memory resource.\r
203\r
204 @param Level The memory test intensive level.\r
205\r
206 @retval EFI_STATUS Success test all the system memory and update\r
207 the memory resource\r
208\r
209**/\r
210EFI_STATUS\r
211PlatformBootManagerMemoryTest (\r
212 IN EXTENDMEM_COVERAGE_LEVEL Level\r
213 )\r
214{\r
215 EFI_STATUS Status;\r
216 EFI_STATUS KeyStatus;\r
217 EFI_STATUS InitStatus;\r
218 EFI_STATUS ReturnStatus;\r
219 BOOLEAN RequireSoftECCInit;\r
220 EFI_GENERIC_MEMORY_TEST_PROTOCOL *GenMemoryTest;\r
221 UINT64 TestedMemorySize;\r
222 UINT64 TotalMemorySize;\r
223 UINTN TestPercent;\r
224 UINT64 PreviousValue;\r
225 BOOLEAN ErrorOut;\r
226 BOOLEAN TestAbort;\r
227 EFI_INPUT_KEY Key;\r
228 CHAR16 StrPercent[80];\r
229 CHAR16 *StrTotalMemory;\r
230 CHAR16 *Pos;\r
231 CHAR16 *TmpStr;\r
232 EFI_GRAPHICS_OUTPUT_BLT_PIXEL Foreground;\r
233 EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background;\r
234 EFI_GRAPHICS_OUTPUT_BLT_PIXEL Color;\r
235 UINT32 TempData;\r
236 UINTN StrTotalMemorySize;\r
237\r
238 ReturnStatus = EFI_SUCCESS;\r
239 ZeroMem (&Key, sizeof (EFI_INPUT_KEY));\r
240\r
241 StrTotalMemorySize = 128;\r
242 Pos = AllocateZeroPool (StrTotalMemorySize);\r
243 ASSERT (Pos != NULL);\r
244\r
245 if (gStringPackHandle == NULL) { \r
246 gStringPackHandle = HiiAddPackages (\r
247 &mPlatformBootManagerStringPackGuid,\r
248 gImageHandle,\r
249 PlatformBootManagerLibStrings,\r
250 NULL\r
251 );\r
252 ASSERT (gStringPackHandle != NULL);\r
253 }\r
254\r
255 StrTotalMemory = Pos;\r
256\r
257 TestedMemorySize = 0;\r
258 TotalMemorySize = 0;\r
259 PreviousValue = 0;\r
260 ErrorOut = FALSE;\r
261 TestAbort = FALSE;\r
262\r
263 SetMem (&Foreground, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0xff);\r
264 SetMem (&Background, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0x0);\r
265 SetMem (&Color, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0xff);\r
266\r
267 RequireSoftECCInit = FALSE;\r
268\r
269 Status = gBS->LocateProtocol (\r
270 &gEfiGenericMemTestProtocolGuid,\r
271 NULL,\r
272 (VOID **) &GenMemoryTest\r
273 );\r
274 if (EFI_ERROR (Status)) {\r
275 FreePool (Pos);\r
276 return EFI_SUCCESS;\r
277 }\r
278\r
279 InitStatus = GenMemoryTest->MemoryTestInit (\r
280 GenMemoryTest,\r
281 Level,\r
282 &RequireSoftECCInit\r
283 );\r
284 if (InitStatus == EFI_NO_MEDIA) {\r
285 //\r
286 // The PEI codes also have the relevant memory test code to check the memory,\r
287 // it can select to test some range of the memory or all of them. If PEI code\r
288 // checks all the memory, this BDS memory test will has no not-test memory to\r
289 // do the test, and then the status of EFI_NO_MEDIA will be returned by\r
290 // "MemoryTestInit". So it does not need to test memory again, just return.\r
291 //\r
292 FreePool (Pos);\r
293 return EFI_SUCCESS;\r
294 }\r
295 \r
296 if (!FeaturePcdGet(PcdBootlogoOnlyEnable)) {\r
297 TmpStr = HiiGetString (gStringPackHandle, STRING_TOKEN (STR_ESC_TO_SKIP_MEM_TEST), NULL);\r
298\r
299 if (TmpStr != NULL) {\r
300 PrintXY (10, 10, NULL, NULL, TmpStr);\r
301 FreePool (TmpStr);\r
302 }\r
303 } else {\r
304 DEBUG ((EFI_D_INFO, "Enter memory test.\n"));\r
305 }\r
306 do {\r
307 Status = GenMemoryTest->PerformMemoryTest (\r
308 GenMemoryTest,\r
309 &TestedMemorySize,\r
310 &TotalMemorySize,\r
311 &ErrorOut,\r
312 TestAbort\r
313 );\r
314 if (ErrorOut && (Status == EFI_DEVICE_ERROR)) {\r
315 TmpStr = HiiGetString (gStringPackHandle, STRING_TOKEN (STR_SYSTEM_MEM_ERROR), NULL);\r
316 if (TmpStr != NULL) {\r
317 PrintXY (10, 10, NULL, NULL, TmpStr);\r
318 FreePool (TmpStr);\r
319 }\r
320\r
321 ASSERT (0);\r
322 }\r
323 \r
324 if (!FeaturePcdGet(PcdBootlogoOnlyEnable)) {\r
325 TempData = (UINT32) DivU64x32 (TotalMemorySize, 16);\r
326 TestPercent = (UINTN) DivU64x32 (\r
327 DivU64x32 (MultU64x32 (TestedMemorySize, 100), 16),\r
328 TempData\r
329 );\r
330 if (TestPercent != PreviousValue) {\r
331 UnicodeValueToString (StrPercent, 0, TestPercent, 0);\r
332 TmpStr = HiiGetString (gStringPackHandle, STRING_TOKEN (STR_MEMORY_TEST_PERCENT), NULL);\r
333 if (TmpStr != NULL) {\r
334 //\r
335 // TmpStr size is 64, StrPercent is reserved to 16.\r
336 //\r
337 StrnCatS (\r
338 StrPercent,\r
339 sizeof (StrPercent) / sizeof (CHAR16), \r
340 TmpStr,\r
341 sizeof (StrPercent) / sizeof (CHAR16) - StrLen (StrPercent) - 1\r
342 );\r
343 PrintXY (10, 10, NULL, NULL, StrPercent);\r
344 FreePool (TmpStr);\r
345 }\r
346\r
347 TmpStr = HiiGetString (gStringPackHandle, STRING_TOKEN (STR_PERFORM_MEM_TEST), NULL);\r
348 if (TmpStr != NULL) {\r
349 PlatformBootManagerShowProgress (\r
350 Foreground,\r
351 Background,\r
352 TmpStr,\r
353 Color,\r
354 TestPercent,\r
355 (UINTN) PreviousValue\r
356 );\r
357 FreePool (TmpStr);\r
358 }\r
359 }\r
360\r
361 PreviousValue = TestPercent;\r
362 } else {\r
363 DEBUG ((EFI_D_INFO, "Perform memory test (ESC to skip).\n"));\r
364 }\r
365\r
366 if (!PcdGetBool (PcdConInConnectOnDemand)) {\r
367 KeyStatus = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);\r
368 if (!EFI_ERROR (KeyStatus) && (Key.ScanCode == SCAN_ESC)) {\r
369 if (!RequireSoftECCInit) {\r
370 if (!FeaturePcdGet(PcdBootlogoOnlyEnable)) {\r
371 TmpStr = HiiGetString (gStringPackHandle, STRING_TOKEN (STR_PERFORM_MEM_TEST), NULL);\r
372 if (TmpStr != NULL) {\r
373 PlatformBootManagerShowProgress (\r
374 Foreground,\r
375 Background,\r
376 TmpStr,\r
377 Color,\r
378 100,\r
379 (UINTN) PreviousValue\r
380 );\r
381 FreePool (TmpStr);\r
382 }\r
383\r
384 PrintXY (10, 10, NULL, NULL, L"100");\r
385 }\r
386 Status = GenMemoryTest->Finished (GenMemoryTest);\r
387 goto Done;\r
388 }\r
389\r
390 TestAbort = TRUE;\r
391 }\r
392 }\r
393 } while (Status != EFI_NOT_FOUND);\r
394\r
395 Status = GenMemoryTest->Finished (GenMemoryTest);\r
396\r
397Done:\r
398 if (!FeaturePcdGet(PcdBootlogoOnlyEnable)) {\r
399 UnicodeValueToString (StrTotalMemory, COMMA_TYPE, TotalMemorySize, 0);\r
400 if (StrTotalMemory[0] == L',') {\r
401 StrTotalMemory++;\r
402 StrTotalMemorySize -= sizeof (CHAR16);\r
403 }\r
404\r
405 TmpStr = HiiGetString (gStringPackHandle, STRING_TOKEN (STR_MEM_TEST_COMPLETED), NULL);\r
406 if (TmpStr != NULL) {\r
407 StrnCatS (\r
408 StrTotalMemory,\r
409 StrTotalMemorySize / sizeof (CHAR16),\r
410 TmpStr,\r
411 StrTotalMemorySize / sizeof (CHAR16) - StrLen (StrTotalMemory) - 1\r
412 );\r
413 FreePool (TmpStr);\r
414 }\r
415\r
416 PrintXY (10, 10, NULL, NULL, StrTotalMemory);\r
417 PlatformBootManagerShowProgress (\r
418 Foreground,\r
419 Background,\r
420 StrTotalMemory,\r
421 Color,\r
422 100,\r
423 (UINTN) PreviousValue\r
424 );\r
425 \r
426 } else {\r
427 DEBUG ((EFI_D_INFO, "%d bytes of system memory tested OK\r\n", TotalMemorySize));\r
428 }\r
429 \r
430 FreePool (Pos);\r
431 return ReturnStatus;\r
432}\r
433\r
434/**\r
435 Convert a *.BMP graphics image to a GOP blt buffer. If a NULL Blt buffer\r
436 is passed in a GopBlt buffer will be allocated by this routine. If a GopBlt\r
437 buffer is passed in it will be used if it is big enough.\r
438\r
439 @param BmpImage Pointer to BMP file\r
440 @param BmpImageSize Number of bytes in BmpImage\r
441 @param GopBlt Buffer containing GOP version of BmpImage.\r
442 @param GopBltSize Size of GopBlt in bytes.\r
443 @param PixelHeight Height of GopBlt/BmpImage in pixels\r
444 @param PixelWidth Width of GopBlt/BmpImage in pixels\r
445\r
446 @retval EFI_SUCCESS GopBlt and GopBltSize are returned.\r
447 @retval EFI_UNSUPPORTED BmpImage is not a valid *.BMP image\r
448 @retval EFI_BUFFER_TOO_SMALL The passed in GopBlt buffer is not big enough.\r
449 GopBltSize will contain the required size.\r
450 @retval EFI_OUT_OF_RESOURCES No enough buffer to allocate.\r
451\r
452**/\r
453EFI_STATUS\r
454PlatformBootManagerConvertBmpToGopBlt (\r
455 IN VOID *BmpImage,\r
456 IN UINTN BmpImageSize,\r
457 IN OUT VOID **GopBlt,\r
458 IN OUT UINTN *GopBltSize,\r
459 OUT UINTN *PixelHeight,\r
460 OUT UINTN *PixelWidth\r
461 )\r
462{\r
463 UINT8 *Image;\r
464 UINT8 *ImageHeader;\r
465 BMP_IMAGE_HEADER *BmpHeader;\r
466 BMP_COLOR_MAP *BmpColorMap;\r
467 EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer;\r
468 EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Blt;\r
469 UINT64 BltBufferSize;\r
470 UINTN Index;\r
471 UINTN Height;\r
472 UINTN Width;\r
473 UINTN ImageIndex;\r
474 UINT32 DataSizePerLine;\r
475 BOOLEAN IsAllocated;\r
476 UINT32 ColorMapNum;\r
477\r
478 if (sizeof (BMP_IMAGE_HEADER) > BmpImageSize) {\r
479 return EFI_INVALID_PARAMETER;\r
480 }\r
481\r
482 BmpHeader = (BMP_IMAGE_HEADER *) BmpImage;\r
483\r
484 if (BmpHeader->CharB != 'B' || BmpHeader->CharM != 'M') {\r
485 return EFI_UNSUPPORTED;\r
486 }\r
487\r
488 //\r
489 // Doesn't support compress.\r
490 //\r
491 if (BmpHeader->CompressionType != 0) {\r
492 return EFI_UNSUPPORTED;\r
493 }\r
494\r
495 //\r
496 // Only support BITMAPINFOHEADER format.\r
497 // BITMAPFILEHEADER + BITMAPINFOHEADER = BMP_IMAGE_HEADER\r
498 //\r
499 if (BmpHeader->HeaderSize != sizeof (BMP_IMAGE_HEADER) - OFFSET_OF(BMP_IMAGE_HEADER, HeaderSize)) {\r
500 return EFI_UNSUPPORTED;\r
501 }\r
502\r
503 //\r
504 // The data size in each line must be 4 byte alignment.\r
505 //\r
506 DataSizePerLine = ((BmpHeader->PixelWidth * BmpHeader->BitPerPixel + 31) >> 3) & (~0x3);\r
507 BltBufferSize = MultU64x32 (DataSizePerLine, BmpHeader->PixelHeight);\r
508 if (BltBufferSize > (UINT32) ~0) {\r
509 return EFI_INVALID_PARAMETER;\r
510 }\r
511\r
512 if ((BmpHeader->Size != BmpImageSize) || \r
513 (BmpHeader->Size < BmpHeader->ImageOffset) ||\r
514 (BmpHeader->Size - BmpHeader->ImageOffset != BmpHeader->PixelHeight * DataSizePerLine)) {\r
515 return EFI_INVALID_PARAMETER;\r
516 }\r
517\r
518 //\r
519 // Calculate Color Map offset in the image.\r
520 //\r
521 Image = BmpImage;\r
522 BmpColorMap = (BMP_COLOR_MAP *) (Image + sizeof (BMP_IMAGE_HEADER));\r
523 if (BmpHeader->ImageOffset < sizeof (BMP_IMAGE_HEADER)) {\r
524 return EFI_INVALID_PARAMETER;\r
525 }\r
526\r
527 if (BmpHeader->ImageOffset > sizeof (BMP_IMAGE_HEADER)) {\r
528 switch (BmpHeader->BitPerPixel) {\r
529 case 1:\r
530 ColorMapNum = 2;\r
531 break;\r
532 case 4:\r
533 ColorMapNum = 16;\r
534 break;\r
535 case 8:\r
536 ColorMapNum = 256;\r
537 break;\r
538 default:\r
539 ColorMapNum = 0;\r
540 break;\r
541 }\r
542 //\r
543 // BMP file may has padding data between the bmp header section and the bmp data section.\r
544 //\r
545 if (BmpHeader->ImageOffset - sizeof (BMP_IMAGE_HEADER) < sizeof (BMP_COLOR_MAP) * ColorMapNum) {\r
546 return EFI_INVALID_PARAMETER;\r
547 }\r
548 }\r
549\r
550 //\r
551 // Calculate graphics image data address in the image\r
552 //\r
553 Image = ((UINT8 *) BmpImage) + BmpHeader->ImageOffset;\r
554 ImageHeader = Image;\r
555\r
556 //\r
557 // Calculate the BltBuffer needed size.\r
558 //\r
559 BltBufferSize = MultU64x32 ((UINT64) BmpHeader->PixelWidth, BmpHeader->PixelHeight);\r
560 //\r
561 // Ensure the BltBufferSize * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) doesn't overflow\r
562 //\r
563 if (BltBufferSize > DivU64x32 ((UINTN) ~0, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL))) {\r
564 return EFI_UNSUPPORTED;\r
565 }\r
566 BltBufferSize = MultU64x32 (BltBufferSize, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));\r
567\r
568 IsAllocated = FALSE;\r
569 if (*GopBlt == NULL) {\r
570 //\r
571 // GopBlt is not allocated by caller.\r
572 //\r
573 *GopBltSize = (UINTN) BltBufferSize;\r
574 *GopBlt = AllocatePool (*GopBltSize);\r
575 IsAllocated = TRUE;\r
576 if (*GopBlt == NULL) {\r
577 return EFI_OUT_OF_RESOURCES;\r
578 }\r
579 } else {\r
580 //\r
581 // GopBlt has been allocated by caller.\r
582 //\r
583 if (*GopBltSize < (UINTN) BltBufferSize) {\r
584 *GopBltSize = (UINTN) BltBufferSize;\r
585 return EFI_BUFFER_TOO_SMALL;\r
586 }\r
587 }\r
588\r
589 *PixelWidth = BmpHeader->PixelWidth;\r
590 *PixelHeight = BmpHeader->PixelHeight;\r
591\r
592 //\r
593 // Convert image from BMP to Blt buffer format\r
594 //\r
595 BltBuffer = *GopBlt;\r
596 for (Height = 0; Height < BmpHeader->PixelHeight; Height++) {\r
597 Blt = &BltBuffer[(BmpHeader->PixelHeight - Height - 1) * BmpHeader->PixelWidth];\r
598 for (Width = 0; Width < BmpHeader->PixelWidth; Width++, Image++, Blt++) {\r
599 switch (BmpHeader->BitPerPixel) {\r
600 case 1:\r
601 //\r
602 // Convert 1-bit (2 colors) BMP to 24-bit color\r
603 //\r
604 for (Index = 0; Index < 8 && Width < BmpHeader->PixelWidth; Index++) {\r
605 Blt->Red = BmpColorMap[((*Image) >> (7 - Index)) & 0x1].Red;\r
606 Blt->Green = BmpColorMap[((*Image) >> (7 - Index)) & 0x1].Green;\r
607 Blt->Blue = BmpColorMap[((*Image) >> (7 - Index)) & 0x1].Blue;\r
608 Blt++;\r
609 Width++;\r
610 }\r
611\r
612 Blt--;\r
613 Width--;\r
614 break;\r
615\r
616 case 4:\r
617 //\r
618 // Convert 4-bit (16 colors) BMP Palette to 24-bit color\r
619 //\r
620 Index = (*Image) >> 4;\r
621 Blt->Red = BmpColorMap[Index].Red;\r
622 Blt->Green = BmpColorMap[Index].Green;\r
623 Blt->Blue = BmpColorMap[Index].Blue;\r
624 if (Width < (BmpHeader->PixelWidth - 1)) {\r
625 Blt++;\r
626 Width++;\r
627 Index = (*Image) & 0x0f;\r
628 Blt->Red = BmpColorMap[Index].Red;\r
629 Blt->Green = BmpColorMap[Index].Green;\r
630 Blt->Blue = BmpColorMap[Index].Blue;\r
631 }\r
632 break;\r
633\r
634 case 8:\r
635 //\r
636 // Convert 8-bit (256 colors) BMP Palette to 24-bit color\r
637 //\r
638 Blt->Red = BmpColorMap[*Image].Red;\r
639 Blt->Green = BmpColorMap[*Image].Green;\r
640 Blt->Blue = BmpColorMap[*Image].Blue;\r
641 break;\r
642\r
643 case 24:\r
644 //\r
645 // It is 24-bit BMP.\r
646 //\r
647 Blt->Blue = *Image++;\r
648 Blt->Green = *Image++;\r
649 Blt->Red = *Image;\r
650 break;\r
651\r
652 default:\r
653 //\r
654 // Other bit format BMP is not supported.\r
655 //\r
656 if (IsAllocated) {\r
657 FreePool (*GopBlt);\r
658 *GopBlt = NULL;\r
659 }\r
660 return EFI_UNSUPPORTED;\r
661 break;\r
662 };\r
663\r
664 }\r
665\r
666 ImageIndex = (UINTN) (Image - ImageHeader);\r
667 if ((ImageIndex % 4) != 0) {\r
668 //\r
669 // Bmp Image starts each row on a 32-bit boundary!\r
670 //\r
671 Image = Image + (4 - (ImageIndex % 4));\r
672 }\r
673 }\r
674\r
675 return EFI_SUCCESS;\r
676}\r
677\r
678/**\r
679 Use SystemTable Conout to stop video based Simple Text Out consoles from going\r
680 to the video device. Put up LogoFile on every video device that is a console.\r
681\r
682 @param[in] LogoFile File name of logo to display on the center of the screen.\r
683\r
684 @retval EFI_SUCCESS ConsoleControl has been flipped to graphics and logo displayed.\r
685 @retval EFI_UNSUPPORTED Logo not found\r
686\r
687**/\r
688EFI_STATUS\r
689PlatformBootManagerEnableQuietBoot (\r
690 IN EFI_GUID *LogoFile\r
691 )\r
692{\r
693 EFI_STATUS Status;\r
694 EFI_OEM_BADGING_PROTOCOL *Badging;\r
695 UINT32 SizeOfX;\r
696 UINT32 SizeOfY;\r
697 INTN DestX;\r
698 INTN DestY;\r
699 UINT8 *ImageData;\r
700 UINTN ImageSize;\r
701 UINTN BltSize;\r
702 UINT32 Instance;\r
703 EFI_BADGING_FORMAT Format;\r
704 EFI_BADGING_DISPLAY_ATTRIBUTE Attribute;\r
705 UINTN CoordinateX;\r
706 UINTN CoordinateY;\r
707 UINTN Height;\r
708 UINTN Width;\r
709 EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Blt;\r
710 EFI_UGA_DRAW_PROTOCOL *UgaDraw;\r
711 UINT32 ColorDepth;\r
712 UINT32 RefreshRate;\r
713 EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;\r
714 EFI_BOOT_LOGO_PROTOCOL *BootLogo;\r
715 UINTN NumberOfLogos;\r
716 EFI_GRAPHICS_OUTPUT_BLT_PIXEL *LogoBlt;\r
717 UINTN LogoDestX;\r
718 UINTN LogoDestY;\r
719 UINTN LogoHeight;\r
720 UINTN LogoWidth;\r
721 UINTN NewDestX;\r
722 UINTN NewDestY;\r
723 UINTN NewHeight;\r
724 UINTN NewWidth;\r
725 UINT64 BufferSize;\r
726\r
727 UgaDraw = NULL;\r
728 //\r
729 // Try to open GOP first\r
730 //\r
731 Status = gBS->HandleProtocol (gST->ConsoleOutHandle, &gEfiGraphicsOutputProtocolGuid, (VOID **) &GraphicsOutput);\r
732 if (EFI_ERROR (Status) && FeaturePcdGet (PcdUgaConsumeSupport)) {\r
733 GraphicsOutput = NULL;\r
734 //\r
735 // Open GOP failed, try to open UGA\r
736 //\r
737 Status = gBS->HandleProtocol (gST->ConsoleOutHandle, &gEfiUgaDrawProtocolGuid, (VOID **) &UgaDraw);\r
738 }\r
739 if (EFI_ERROR (Status)) {\r
740 return EFI_UNSUPPORTED;\r
741 }\r
742\r
743 //\r
744 // Try to open Boot Logo Protocol.\r
745 //\r
746 BootLogo = NULL;\r
747 gBS->LocateProtocol (&gEfiBootLogoProtocolGuid, NULL, (VOID **) &BootLogo);\r
748\r
749 //\r
750 // Erase Cursor from screen\r
751 //\r
752 gST->ConOut->EnableCursor (gST->ConOut, FALSE);\r
753\r
754 Badging = NULL;\r
755 Status = gBS->LocateProtocol (&gEfiOEMBadgingProtocolGuid, NULL, (VOID **) &Badging);\r
756\r
757 if (GraphicsOutput != NULL) {\r
758 SizeOfX = GraphicsOutput->Mode->Info->HorizontalResolution;\r
759 SizeOfY = GraphicsOutput->Mode->Info->VerticalResolution;\r
760\r
761 } else if (UgaDraw != NULL && FeaturePcdGet (PcdUgaConsumeSupport)) {\r
762 Status = UgaDraw->GetMode (UgaDraw, &SizeOfX, &SizeOfY, &ColorDepth, &RefreshRate);\r
763 if (EFI_ERROR (Status)) {\r
764 return EFI_UNSUPPORTED;\r
765 }\r
766 } else {\r
767 return EFI_UNSUPPORTED;\r
768 }\r
769\r
770 Blt = NULL;\r
771 NumberOfLogos = 0;\r
772 LogoDestX = 0;\r
773 LogoDestY = 0;\r
774 LogoHeight = 0;\r
775 LogoWidth = 0;\r
776 NewDestX = 0;\r
777 NewDestY = 0;\r
778 NewHeight = 0;\r
779 NewWidth = 0;\r
780 Instance = 0;\r
781 while (1) {\r
782 ImageData = NULL;\r
783 ImageSize = 0;\r
784\r
785 if (Badging != NULL) {\r
786 //\r
787 // Get image from OEMBadging protocol.\r
788 //\r
789 Status = Badging->GetImage (\r
790 Badging,\r
791 &Instance,\r
792 &Format,\r
793 &ImageData,\r
794 &ImageSize,\r
795 &Attribute,\r
796 &CoordinateX,\r
797 &CoordinateY\r
798 );\r
799 if (EFI_ERROR (Status)) {\r
800 goto Done;\r
801 }\r
802\r
803 //\r
804 // Currently only support BMP format.\r
805 //\r
806 if (Format != EfiBadgingFormatBMP) {\r
807 if (ImageData != NULL) {\r
808 FreePool (ImageData);\r
809 }\r
810 continue;\r
811 }\r
812 } else {\r
813 //\r
814 // Get the specified image from FV.\r
815 //\r
816 Status = GetSectionFromAnyFv (LogoFile, EFI_SECTION_RAW, 0, (VOID **) &ImageData, &ImageSize);\r
817 if (EFI_ERROR (Status)) {\r
818 return EFI_UNSUPPORTED;\r
819 }\r
820\r
821 CoordinateX = 0;\r
822 CoordinateY = 0;\r
823 if (!FeaturePcdGet(PcdBootlogoOnlyEnable)) {\r
824 Attribute = EfiBadgingDisplayAttributeCenter;\r
825 } else {\r
826 Attribute = EfiBadgingDisplayAttributeCustomized;\r
827 } \r
828 }\r
829\r
830 if (Blt != NULL) {\r
831 FreePool (Blt);\r
832 }\r
833 Blt = NULL;\r
834 Status = PlatformBootManagerConvertBmpToGopBlt (\r
835 ImageData,\r
836 ImageSize,\r
837 (VOID **) &Blt,\r
838 &BltSize,\r
839 &Height,\r
840 &Width\r
841 );\r
842 if (EFI_ERROR (Status)) {\r
843 FreePool (ImageData);\r
844\r
845 if (Badging == NULL) {\r
846 return Status;\r
847 } else {\r
848 continue;\r
849 }\r
850 }\r
851\r
852 //\r
853 // Calculate the display position according to Attribute.\r
854 //\r
855 switch (Attribute) {\r
856 case EfiBadgingDisplayAttributeLeftTop:\r
857 DestX = CoordinateX;\r
858 DestY = CoordinateY;\r
859 break;\r
860\r
861 case EfiBadgingDisplayAttributeCenterTop:\r
862 DestX = (SizeOfX - Width) / 2;\r
863 DestY = CoordinateY;\r
864 break;\r
865\r
866 case EfiBadgingDisplayAttributeRightTop:\r
867 DestX = (SizeOfX - Width - CoordinateX);\r
868 DestY = CoordinateY;;\r
869 break;\r
870\r
871 case EfiBadgingDisplayAttributeCenterRight:\r
872 DestX = (SizeOfX - Width - CoordinateX);\r
873 DestY = (SizeOfY - Height) / 2;\r
874 break;\r
875\r
876 case EfiBadgingDisplayAttributeRightBottom:\r
877 DestX = (SizeOfX - Width - CoordinateX);\r
878 DestY = (SizeOfY - Height - CoordinateY);\r
879 break;\r
880\r
881 case EfiBadgingDisplayAttributeCenterBottom:\r
882 DestX = (SizeOfX - Width) / 2;\r
883 DestY = (SizeOfY - Height - CoordinateY);\r
884 break;\r
885\r
886 case EfiBadgingDisplayAttributeLeftBottom:\r
887 DestX = CoordinateX;\r
888 DestY = (SizeOfY - Height - CoordinateY);\r
889 break;\r
890\r
891 case EfiBadgingDisplayAttributeCenterLeft:\r
892 DestX = CoordinateX;\r
893 DestY = (SizeOfY - Height) / 2;\r
894 break;\r
895\r
896 case EfiBadgingDisplayAttributeCenter:\r
897 DestX = (SizeOfX - Width) / 2;\r
898 DestY = (SizeOfY - Height) / 2;\r
899 break;\r
900\r
901 case EfiBadgingDisplayAttributeCustomized:\r
902 DestX = (SizeOfX - Width) / 2;\r
903 DestY = ((SizeOfY * 382) / 1000) - Height / 2;\r
904 break;\r
905\r
906 default:\r
907 DestX = CoordinateX;\r
908 DestY = CoordinateY;\r
909 break;\r
910 }\r
911\r
912 if ((DestX >= 0) && (DestY >= 0)) {\r
913 if (GraphicsOutput != NULL) {\r
914 Status = GraphicsOutput->Blt (\r
915 GraphicsOutput,\r
916 Blt,\r
917 EfiBltBufferToVideo,\r
918 0,\r
919 0,\r
920 (UINTN) DestX,\r
921 (UINTN) DestY,\r
922 Width,\r
923 Height,\r
924 Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)\r
925 );\r
926 } else if (UgaDraw != NULL && FeaturePcdGet (PcdUgaConsumeSupport)) {\r
927 Status = UgaDraw->Blt (\r
928 UgaDraw,\r
929 (EFI_UGA_PIXEL *) Blt,\r
930 EfiUgaBltBufferToVideo,\r
931 0,\r
932 0,\r
933 (UINTN) DestX,\r
934 (UINTN) DestY,\r
935 Width,\r
936 Height,\r
937 Width * sizeof (EFI_UGA_PIXEL)\r
938 );\r
939 } else {\r
940 Status = EFI_UNSUPPORTED;\r
941 }\r
942\r
943 //\r
944 // Report displayed Logo information.\r
945 //\r
946 if (!EFI_ERROR (Status)) {\r
947 NumberOfLogos++;\r
948\r
949 if (LogoWidth == 0) {\r
950 //\r
951 // The first Logo.\r
952 //\r
953 LogoDestX = (UINTN) DestX;\r
954 LogoDestY = (UINTN) DestY;\r
955 LogoWidth = Width;\r
956 LogoHeight = Height;\r
957 } else {\r
958 //\r
959 // Merge new logo with old one.\r
960 //\r
961 NewDestX = MIN ((UINTN) DestX, LogoDestX);\r
962 NewDestY = MIN ((UINTN) DestY, LogoDestY);\r
963 NewWidth = MAX ((UINTN) DestX + Width, LogoDestX + LogoWidth) - NewDestX;\r
964 NewHeight = MAX ((UINTN) DestY + Height, LogoDestY + LogoHeight) - NewDestY;\r
965\r
966 LogoDestX = NewDestX;\r
967 LogoDestY = NewDestY;\r
968 LogoWidth = NewWidth;\r
969 LogoHeight = NewHeight;\r
970 }\r
971 }\r
972 }\r
973\r
974 FreePool (ImageData);\r
975\r
976 if (Badging == NULL) {\r
977 break;\r
978 }\r
979 }\r
980\r
981Done:\r
982 if (BootLogo == NULL || NumberOfLogos == 0) {\r
983 //\r
984 // No logo displayed.\r
985 //\r
986 if (Blt != NULL) {\r
987 FreePool (Blt);\r
988 }\r
989\r
990 return Status;\r
991 }\r
992\r
993 //\r
994 // Advertise displayed Logo information.\r
995 //\r
996 if (NumberOfLogos == 1) {\r
997 //\r
998 // Only one logo displayed, use its Blt buffer directly for BootLogo protocol.\r
999 //\r
1000 LogoBlt = Blt;\r
1001 Status = EFI_SUCCESS;\r
1002 } else {\r
1003 //\r
1004 // More than one Logo displayed, get merged BltBuffer using VideoToBuffer operation. \r
1005 //\r
1006 if (Blt != NULL) {\r
1007 FreePool (Blt);\r
1008 }\r
1009\r
1010 //\r
1011 // Ensure the LogoHeight * LogoWidth doesn't overflow\r
1012 //\r
1013 if (LogoHeight > DivU64x64Remainder ((UINTN) ~0, LogoWidth, NULL)) {\r
1014 return EFI_UNSUPPORTED;\r
1015 }\r
1016 BufferSize = MultU64x64 (LogoWidth, LogoHeight);\r
1017\r
1018 //\r
1019 // Ensure the BufferSize * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) doesn't overflow\r
1020 //\r
1021 if (BufferSize > DivU64x32 ((UINTN) ~0, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL))) {\r
1022 return EFI_UNSUPPORTED;\r
1023 }\r
1024\r
1025 LogoBlt = AllocateZeroPool ((UINTN)BufferSize * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));\r
1026 if (LogoBlt == NULL) {\r
1027 return EFI_OUT_OF_RESOURCES;\r
1028 }\r
1029\r
1030 if (GraphicsOutput != NULL) {\r
1031 Status = GraphicsOutput->Blt (\r
1032 GraphicsOutput,\r
1033 LogoBlt,\r
1034 EfiBltVideoToBltBuffer,\r
1035 LogoDestX,\r
1036 LogoDestY,\r
1037 0,\r
1038 0,\r
1039 LogoWidth,\r
1040 LogoHeight,\r
1041 LogoWidth * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)\r
1042 );\r
1043 } else if (UgaDraw != NULL && FeaturePcdGet (PcdUgaConsumeSupport)) {\r
1044 Status = UgaDraw->Blt (\r
1045 UgaDraw,\r
1046 (EFI_UGA_PIXEL *) LogoBlt,\r
1047 EfiUgaVideoToBltBuffer,\r
1048 LogoDestX,\r
1049 LogoDestY,\r
1050 0,\r
1051 0,\r
1052 LogoWidth,\r
1053 LogoHeight,\r
1054 LogoWidth * sizeof (EFI_UGA_PIXEL)\r
1055 );\r
1056 } else {\r
1057 Status = EFI_UNSUPPORTED;\r
1058 }\r
1059 }\r
1060\r
1061 if (!EFI_ERROR (Status)) {\r
1062 BootLogo->SetBootLogo (BootLogo, LogoBlt, LogoDestX, LogoDestY, LogoWidth, LogoHeight);\r
1063 }\r
1064 FreePool (LogoBlt);\r
1065\r
1066 return Status;\r
1067}\r
1068\r
1069/**\r
1070 Use SystemTable Conout to turn on video based Simple Text Out consoles. The \r
1071 Simple Text Out screens will now be synced up with all non video output devices\r
1072\r
1073 @retval EFI_SUCCESS UGA devices are back in text mode and synced up.\r
1074\r
1075**/\r
1076EFI_STATUS\r
1077PlatformBootManagerDisableQuietBoot (\r
1078 VOID\r
1079 )\r
1080{\r
1081 //\r
1082 // Enable Cursor on Screen\r
1083 //\r
1084 gST->ConOut->EnableCursor (gST->ConOut, TRUE);\r
1085 return EFI_SUCCESS;\r
1086}\r