Add DXE_DRIVER to list of supported module types for BaseFileHandleLib.
[mirror_edk2.git] / OvmfPkg / Library / PlatformBdsLib / BdsPlatform.c
CommitLineData
49ba9447 1/** @file\r
2 Platform BDS customizations.\r
3\r
4 Copyright (c) 2004 - 2008, Intel Corporation. <BR>\r
5 All rights reserved. This program and the accompanying materials\r
6 are licensed and made available under the terms and conditions of the BSD License\r
7 which accompanies this distribution. The full text of the license may be found at\r
8 http://opensource.org/licenses/bsd-license.php\r
9\r
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12\r
13**/\r
14\r
15#include "BdsPlatform.h"\r
16\r
17\r
40f2c454 18//\r
19// Global data\r
20//\r
21\r
22VOID *mEfiDevPathNotifyReg;\r
23EFI_EVENT mEfiDevPathEvent;\r
24\r
25\r
26//\r
27// Function prototypes\r
28//\r
29\r
30VOID\r
31InstallDevicePathCallback (\r
32 VOID\r
33 );\r
34\r
5106d422 35STATIC\r
36VOID\r
37LoadVideoRom (\r
ccd4b7da 38 VOID\r
5106d422 39 );\r
40\r
41STATIC\r
42EFI_STATUS\r
43PciRomLoadEfiDriversFromRomImage (\r
44 IN EFI_PHYSICAL_ADDRESS Rom,\r
45 IN UINTN RomSize\r
46 );\r
40f2c454 47\r
49ba9447 48//\r
49// BDS Platform Functions\r
50//\r
51VOID\r
52EFIAPI\r
53PlatformBdsInit (\r
370ec7f1 54 VOID\r
49ba9447 55 )\r
56/*++\r
57\r
58Routine Description:\r
59\r
60 Platform Bds init. Incude the platform firmware vendor, revision\r
61 and so crc check.\r
62\r
63Arguments:\r
64\r
49ba9447 65Returns:\r
66\r
67 None.\r
68\r
69--*/\r
70{\r
71 DEBUG ((EFI_D_INFO, "PlatformBdsInit\n"));\r
40f2c454 72 InstallDevicePathCallback ();\r
5106d422 73 LoadVideoRom ();\r
49ba9447 74}\r
75\r
76\r
77EFI_STATUS\r
78ConnectRootBridge (\r
79 VOID\r
80 )\r
81/*++\r
82\r
83Routine Description:\r
84\r
85 Connect RootBridge\r
86\r
87Arguments:\r
88\r
89 None.\r
90\r
91Returns:\r
92\r
93 EFI_SUCCESS - Connect RootBridge successfully.\r
94 EFI_STATUS - Connect RootBridge fail.\r
95\r
96--*/\r
97{\r
98 EFI_STATUS Status;\r
99 EFI_HANDLE RootHandle;\r
100\r
101 //\r
102 // Make all the PCI_IO protocols on PCI Seg 0 show up\r
103 //\r
104 BdsLibConnectDevicePath (gPlatformRootBridges[0]);\r
105\r
106 Status = gBS->LocateDevicePath (\r
107 &gEfiDevicePathProtocolGuid,\r
108 &gPlatformRootBridges[0],\r
109 &RootHandle\r
110 );\r
111 if (EFI_ERROR (Status)) {\r
112 return Status;\r
113 }\r
114\r
115 Status = gBS->ConnectController (RootHandle, NULL, NULL, FALSE);\r
116 if (EFI_ERROR (Status)) {\r
117 return Status;\r
118 }\r
119\r
120 return EFI_SUCCESS;\r
121}\r
122\r
123\r
124EFI_STATUS\r
125PrepareLpcBridgeDevicePath (\r
126 IN EFI_HANDLE DeviceHandle\r
127 )\r
128/*++\r
129\r
130Routine Description:\r
131\r
132 Add IsaKeyboard to ConIn,\r
133 add IsaSerial to ConOut, ConIn, ErrOut.\r
134 LPC Bridge: 06 01 00\r
135\r
136Arguments:\r
137\r
138 DeviceHandle - Handle of PCIIO protocol.\r
139\r
140Returns:\r
141\r
142 EFI_SUCCESS - LPC bridge is added to ConOut, ConIn, and ErrOut.\r
143 EFI_STATUS - No LPC bridge is added.\r
144\r
145--*/\r
146{\r
147 EFI_STATUS Status;\r
148 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
149 EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;\r
150 CHAR16 *DevPathStr;\r
151\r
152 DevicePath = NULL;\r
153 Status = gBS->HandleProtocol (\r
154 DeviceHandle,\r
155 &gEfiDevicePathProtocolGuid,\r
156 (VOID*)&DevicePath\r
157 );\r
158 if (EFI_ERROR (Status)) {\r
159 return Status;\r
160 }\r
161 TempDevicePath = DevicePath;\r
162\r
163 //\r
164 // Register Keyboard\r
165 //\r
166 DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gPnpPs2KeyboardDeviceNode);\r
167\r
168 BdsLibUpdateConsoleVariable (VarConsoleInp, DevicePath, NULL);\r
169\r
170 //\r
171 // Register COM1\r
172 //\r
173 DevicePath = TempDevicePath;\r
174 gPnp16550ComPortDeviceNode.UID = 0;\r
175\r
176 DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gPnp16550ComPortDeviceNode);\r
177 DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gUartDeviceNode);\r
178 DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gTerminalTypeDeviceNode);\r
179\r
180 //\r
181 // Print Device Path\r
182 //\r
183 DevPathStr = DevicePathToStr(DevicePath);\r
184 DEBUG((\r
185 EFI_D_INFO,\r
186 "BdsPlatform.c+%d: COM%d DevPath: %s\n",\r
187 __LINE__,\r
188 gPnp16550ComPortDeviceNode.UID + 1,\r
189 DevPathStr\r
190 ));\r
191 FreePool(DevPathStr);\r
192\r
193 BdsLibUpdateConsoleVariable (VarConsoleOut, DevicePath, NULL);\r
194 BdsLibUpdateConsoleVariable (VarConsoleInp, DevicePath, NULL);\r
195 BdsLibUpdateConsoleVariable (VarErrorOut, DevicePath, NULL);\r
196\r
197 //\r
198 // Register COM2\r
199 //\r
200 DevicePath = TempDevicePath;\r
201 gPnp16550ComPortDeviceNode.UID = 1;\r
202\r
203 DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gPnp16550ComPortDeviceNode);\r
204 DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gUartDeviceNode);\r
205 DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gTerminalTypeDeviceNode);\r
206\r
207 //\r
208 // Print Device Path\r
209 //\r
210 DevPathStr = DevicePathToStr(DevicePath);\r
211 DEBUG((\r
212 EFI_D_INFO,\r
213 "BdsPlatform.c+%d: COM%d DevPath: %s\n",\r
214 __LINE__,\r
215 gPnp16550ComPortDeviceNode.UID + 1,\r
216 DevPathStr\r
217 ));\r
218 FreePool(DevPathStr);\r
219\r
220 BdsLibUpdateConsoleVariable (VarConsoleOut, DevicePath, NULL);\r
221 BdsLibUpdateConsoleVariable (VarConsoleInp, DevicePath, NULL);\r
222 BdsLibUpdateConsoleVariable (VarErrorOut, DevicePath, NULL);\r
223\r
224 return EFI_SUCCESS;\r
225}\r
226\r
227EFI_STATUS\r
228GetGopDevicePath (\r
229 IN EFI_DEVICE_PATH_PROTOCOL *PciDevicePath,\r
230 OUT EFI_DEVICE_PATH_PROTOCOL **GopDevicePath\r
231 )\r
232{\r
233 UINTN Index;\r
234 EFI_STATUS Status;\r
235 EFI_HANDLE PciDeviceHandle;\r
236 EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;\r
237 EFI_DEVICE_PATH_PROTOCOL *TempPciDevicePath;\r
238 UINTN GopHandleCount;\r
239 EFI_HANDLE *GopHandleBuffer;\r
240\r
241 if (PciDevicePath == NULL || GopDevicePath == NULL) {\r
242 return EFI_INVALID_PARAMETER;\r
243 }\r
244\r
245 //\r
246 // Initialize the GopDevicePath to be PciDevicePath\r
247 //\r
248 *GopDevicePath = PciDevicePath;\r
249 TempPciDevicePath = PciDevicePath;\r
250\r
251 Status = gBS->LocateDevicePath (\r
252 &gEfiDevicePathProtocolGuid,\r
253 &TempPciDevicePath,\r
254 &PciDeviceHandle\r
255 );\r
256 if (EFI_ERROR (Status)) {\r
257 return Status;\r
258 }\r
259\r
260 //\r
261 // Try to connect this handle, so that GOP dirver could start on this\r
262 // device and create child handles with GraphicsOutput Protocol installed\r
263 // on them, then we get device paths of these child handles and select\r
264 // them as possible console device.\r
265 //\r
266 gBS->ConnectController (PciDeviceHandle, NULL, NULL, FALSE);\r
267\r
268 Status = gBS->LocateHandleBuffer (\r
269 ByProtocol,\r
270 &gEfiGraphicsOutputProtocolGuid,\r
271 NULL,\r
272 &GopHandleCount,\r
273 &GopHandleBuffer\r
274 );\r
275 if (!EFI_ERROR (Status)) {\r
276 //\r
277 // Add all the child handles as possible Console Device\r
278 //\r
279 for (Index = 0; Index < GopHandleCount; Index++) {\r
280 Status = gBS->HandleProtocol (GopHandleBuffer[Index], &gEfiDevicePathProtocolGuid, (VOID*)&TempDevicePath);\r
281 if (EFI_ERROR (Status)) {\r
282 continue;\r
283 }\r
284 if (CompareMem (\r
285 PciDevicePath,\r
286 TempDevicePath,\r
287 GetDevicePathSize (PciDevicePath) - END_DEVICE_PATH_LENGTH\r
288 ) == 0) {\r
289 //\r
290 // In current implementation, we only enable one of the child handles\r
291 // as console device, i.e. sotre one of the child handle's device\r
292 // path to variable "ConOut"\r
293 // In futhure, we could select all child handles to be console device\r
294 //\r
295\r
296 *GopDevicePath = TempDevicePath;\r
297\r
298 //\r
299 // Delete the PCI device's path that added by GetPlugInPciVgaDevicePath()\r
300 // Add the integrity GOP device path.\r
301 //\r
302 BdsLibUpdateConsoleVariable (VarConsoleOutDev, NULL, PciDevicePath);\r
303 BdsLibUpdateConsoleVariable (VarConsoleOutDev, TempDevicePath, NULL);\r
304 }\r
305 }\r
306 gBS->FreePool (GopHandleBuffer);\r
307 }\r
308\r
309 return EFI_SUCCESS;\r
310}\r
311\r
312EFI_STATUS\r
313PreparePciVgaDevicePath (\r
314 IN EFI_HANDLE DeviceHandle\r
315 )\r
316/*++\r
317\r
318Routine Description:\r
319\r
320 Add PCI VGA to ConOut.\r
321 PCI VGA: 03 00 00\r
322\r
323Arguments:\r
324\r
325 DeviceHandle - Handle of PCIIO protocol.\r
326\r
327Returns:\r
328\r
329 EFI_SUCCESS - PCI VGA is added to ConOut.\r
330 EFI_STATUS - No PCI VGA device is added.\r
331\r
332--*/\r
333{\r
334 EFI_STATUS Status;\r
335 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
336 EFI_DEVICE_PATH_PROTOCOL *GopDevicePath;\r
337\r
338 DevicePath = NULL;\r
339 Status = gBS->HandleProtocol (\r
340 DeviceHandle,\r
341 &gEfiDevicePathProtocolGuid,\r
342 (VOID*)&DevicePath\r
343 );\r
344 if (EFI_ERROR (Status)) {\r
345 return Status;\r
346 }\r
347\r
348 GetGopDevicePath (DevicePath, &GopDevicePath);\r
349 DevicePath = GopDevicePath;\r
350\r
351 BdsLibUpdateConsoleVariable (VarConsoleOut, DevicePath, NULL);\r
352\r
353 return EFI_SUCCESS;\r
354}\r
355\r
356EFI_STATUS\r
357PreparePciSerialDevicePath (\r
358 IN EFI_HANDLE DeviceHandle\r
359 )\r
360/*++\r
361\r
362Routine Description:\r
363\r
364 Add PCI Serial to ConOut, ConIn, ErrOut.\r
365 PCI Serial: 07 00 02\r
366\r
367Arguments:\r
368\r
369 DeviceHandle - Handle of PCIIO protocol.\r
370\r
371Returns:\r
372\r
373 EFI_SUCCESS - PCI Serial is added to ConOut, ConIn, and ErrOut.\r
374 EFI_STATUS - No PCI Serial device is added.\r
375\r
376--*/\r
377{\r
378 EFI_STATUS Status;\r
379 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
380\r
381 DevicePath = NULL;\r
382 Status = gBS->HandleProtocol (\r
383 DeviceHandle,\r
384 &gEfiDevicePathProtocolGuid,\r
385 (VOID*)&DevicePath\r
386 );\r
387 if (EFI_ERROR (Status)) {\r
388 return Status;\r
389 }\r
390\r
391 DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gUartDeviceNode);\r
392 DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gTerminalTypeDeviceNode);\r
393\r
394 BdsLibUpdateConsoleVariable (VarConsoleOut, DevicePath, NULL);\r
395 BdsLibUpdateConsoleVariable (VarConsoleInp, DevicePath, NULL);\r
396 BdsLibUpdateConsoleVariable (VarErrorOut, DevicePath, NULL);\r
397\r
398 return EFI_SUCCESS;\r
399}\r
400\r
401EFI_STATUS\r
402DetectAndPreparePlatformPciDevicePath (\r
403 BOOLEAN DetectVgaOnly\r
404 )\r
405/*++\r
406\r
407Routine Description:\r
408\r
409 Do platform specific PCI Device check and add them to ConOut, ConIn, ErrOut\r
410\r
411Arguments:\r
412\r
413 DetectVgaOnly - Only detect VGA device if it's TRUE.\r
414\r
415Returns:\r
416\r
417 EFI_SUCCESS - PCI Device check and Console variable update successfully.\r
418 EFI_STATUS - PCI Device check or Console variable update fail.\r
419\r
420--*/\r
421{\r
422 EFI_STATUS Status;\r
423 UINTN HandleCount;\r
424 EFI_HANDLE *HandleBuffer;\r
425 UINTN Index;\r
426 EFI_PCI_IO_PROTOCOL *PciIo;\r
427 PCI_TYPE00 Pci;\r
428\r
429 //\r
430 // Start to check all the PciIo to find all possible device\r
431 //\r
432 HandleCount = 0;\r
433 HandleBuffer = NULL;\r
434 Status = gBS->LocateHandleBuffer (\r
435 ByProtocol,\r
436 &gEfiPciIoProtocolGuid,\r
437 NULL,\r
438 &HandleCount,\r
439 &HandleBuffer\r
440 );\r
441 if (EFI_ERROR (Status)) {\r
442 return Status;\r
443 }\r
444\r
445 for (Index = 0; Index < HandleCount; Index++) {\r
446 Status = gBS->HandleProtocol (HandleBuffer[Index], &gEfiPciIoProtocolGuid, (VOID*)&PciIo);\r
447 if (EFI_ERROR (Status)) {\r
448 continue;\r
449 }\r
450\r
451 //\r
452 // Check for all PCI device\r
453 //\r
454 Status = PciIo->Pci.Read (\r
455 PciIo,\r
456 EfiPciIoWidthUint32,\r
457 0,\r
458 sizeof (Pci) / sizeof (UINT32),\r
459 &Pci\r
460 );\r
461 if (EFI_ERROR (Status)) {\r
462 continue;\r
463 }\r
464\r
607ca510 465 Status = PciIo->Attributes (\r
466 PciIo,\r
467 EfiPciIoAttributeOperationEnable,\r
468 EFI_PCI_DEVICE_ENABLE,\r
469 NULL\r
470 );\r
471 ASSERT_EFI_ERROR (Status);\r
472\r
49ba9447 473 if (!DetectVgaOnly) {\r
474 //\r
475 // Here we decide whether it is LPC Bridge\r
476 //\r
477 if ((IS_PCI_LPC (&Pci)) ||\r
478 ((IS_PCI_ISA_PDECODE (&Pci)) &&\r
479 (Pci.Hdr.VendorId == 0x8086) &&\r
480 (Pci.Hdr.DeviceId == 0x7000)\r
481 )\r
482 ) {\r
49ba9447 483 //\r
484 // Add IsaKeyboard to ConIn,\r
485 // add IsaSerial to ConOut, ConIn, ErrOut\r
486 //\r
607ca510 487 DEBUG ((EFI_D_INFO, "Found LPC Bridge device\n"));\r
49ba9447 488 PrepareLpcBridgeDevicePath (HandleBuffer[Index]);\r
489 continue;\r
490 }\r
491 //\r
492 // Here we decide which Serial device to enable in PCI bus\r
493 //\r
494 if (IS_PCI_16550SERIAL (&Pci)) {\r
495 //\r
496 // Add them to ConOut, ConIn, ErrOut.\r
497 //\r
607ca510 498 DEBUG ((EFI_D_INFO, "Found PCI 16550 SERIAL device\n"));\r
49ba9447 499 PreparePciSerialDevicePath (HandleBuffer[Index]);\r
500 continue;\r
501 }\r
502 }\r
503\r
49ba9447 504 //\r
505 // Here we decide which VGA device to enable in PCI bus\r
506 //\r
507 if (IS_PCI_VGA (&Pci)) {\r
508 //\r
509 // Add them to ConOut.\r
510 //\r
607ca510 511 DEBUG ((EFI_D_INFO, "Found PCI VGA device\n"));\r
49ba9447 512 PreparePciVgaDevicePath (HandleBuffer[Index]);\r
513 continue;\r
514 }\r
515 }\r
516\r
517 gBS->FreePool (HandleBuffer);\r
518\r
519 return EFI_SUCCESS;\r
520}\r
521\r
522\r
523EFI_STATUS\r
524PlatformBdsConnectConsole (\r
525 IN BDS_CONSOLE_CONNECT_ENTRY *PlatformConsole\r
526 )\r
527/*++\r
528\r
529Routine Description:\r
530\r
531 Connect the predefined platform default console device. Always try to find\r
532 and enable the vga device if have.\r
533\r
534Arguments:\r
535\r
536 PlatformConsole - Predfined platform default console device array.\r
537\r
538Returns:\r
539\r
540 EFI_SUCCESS - Success connect at least one ConIn and ConOut\r
541 device, there must have one ConOut device is\r
542 active vga device.\r
543\r
544 EFI_STATUS - Return the status of\r
545 BdsLibConnectAllDefaultConsoles ()\r
546\r
547--*/\r
548{\r
549 EFI_STATUS Status;\r
550 UINTN Index;\r
551 EFI_DEVICE_PATH_PROTOCOL *VarConout;\r
552 EFI_DEVICE_PATH_PROTOCOL *VarConin;\r
553 UINTN DevicePathSize;\r
554\r
555 //\r
556 // Connect RootBridge\r
557 //\r
558 ConnectRootBridge ();\r
559\r
560 VarConout = BdsLibGetVariableAndSize (\r
561 VarConsoleOut,\r
562 &gEfiGlobalVariableGuid,\r
563 &DevicePathSize\r
564 );\r
565 VarConin = BdsLibGetVariableAndSize (\r
566 VarConsoleInp,\r
567 &gEfiGlobalVariableGuid,\r
568 &DevicePathSize\r
569 );\r
570\r
571 if (VarConout == NULL || VarConin == NULL) {\r
572 //\r
573 // Do platform specific PCI Device check and add them to ConOut, ConIn, ErrOut\r
574 //\r
575 DetectAndPreparePlatformPciDevicePath (FALSE);\r
576\r
577 //\r
578 // Have chance to connect the platform default console,\r
579 // the platform default console is the minimue device group\r
580 // the platform should support\r
581 //\r
582 for (Index = 0; PlatformConsole[Index].DevicePath != NULL; ++Index) {\r
583 //\r
584 // Update the console variable with the connect type\r
585 //\r
586 if ((PlatformConsole[Index].ConnectType & CONSOLE_IN) == CONSOLE_IN) {\r
587 BdsLibUpdateConsoleVariable (VarConsoleInp, PlatformConsole[Index].DevicePath, NULL);\r
588 }\r
589 if ((PlatformConsole[Index].ConnectType & CONSOLE_OUT) == CONSOLE_OUT) {\r
590 BdsLibUpdateConsoleVariable (VarConsoleOut, PlatformConsole[Index].DevicePath, NULL);\r
591 }\r
592 if ((PlatformConsole[Index].ConnectType & STD_ERROR) == STD_ERROR) {\r
593 BdsLibUpdateConsoleVariable (VarErrorOut, PlatformConsole[Index].DevicePath, NULL);\r
594 }\r
595 }\r
596 } else {\r
597 //\r
598 // Only detect VGA device and add them to ConOut\r
599 //\r
600 DetectAndPreparePlatformPciDevicePath (TRUE);\r
601 }\r
602\r
603 //\r
604 // Connect the all the default console with current cosole variable\r
605 //\r
606 Status = BdsLibConnectAllDefaultConsoles ();\r
607 if (EFI_ERROR (Status)) {\r
608 return Status;\r
609 }\r
610\r
611 return EFI_SUCCESS;\r
612}\r
613\r
614\r
615VOID\r
616PciInitialization (\r
617 )\r
618{\r
619 //\r
40f2c454 620 // Bus 0, Device 0, Function 0 - Host to PCI Bridge\r
621 //\r
622 PciWrite8 (PCI_LIB_ADDRESS (0, 0, 0, 0x3c), 0x00);\r
623\r
624 //\r
625 // Bus 0, Device 1, Function 0 - PCI to ISA Bridge\r
49ba9447 626 //\r
40f2c454 627 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x3c), 0x00);\r
628 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x60), 0x0b);\r
629 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x61), 0x09);\r
630 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x62), 0x0b);\r
631 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x63), 0x09);\r
49ba9447 632\r
633 //\r
40f2c454 634 // Bus 0, Device 1, Function 1 - IDE Controller\r
49ba9447 635 //\r
40f2c454 636 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 1, 0x3c), 0x00);\r
637 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 1, 0x0d), 0x40);\r
49ba9447 638\r
639 //\r
40f2c454 640 // Bus 0, Device 1, Function 3 - Power Managment Controller\r
49ba9447 641 //\r
40f2c454 642 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 3, 0x3c), 0x0b);\r
643 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 3, 0x3d), 0x01);\r
49ba9447 644\r
645 //\r
40f2c454 646 // Bus 0, Device 2, Function 0 - Video Controller\r
49ba9447 647 //\r
40f2c454 648 PciWrite8 (PCI_LIB_ADDRESS (0, 2, 0, 0x3c), 0x00);\r
49ba9447 649\r
650 //\r
40f2c454 651 // Bus 0, Device 3, Function 0 - Network Controller\r
49ba9447 652 //\r
40f2c454 653 PciWrite8 (PCI_LIB_ADDRESS (0, 3, 0, 0x3c), 0x0b);\r
654 PciWrite8 (PCI_LIB_ADDRESS (0, 3, 0, 0x3d), 0x01);\r
49ba9447 655\r
656 //\r
40f2c454 657 // Bus 0, Device 4, Function 0 - RAM Memory\r
49ba9447 658 //\r
40f2c454 659 PciWrite8 (PCI_LIB_ADDRESS (0, 4, 0, 0x3c), 0x09);\r
660 PciWrite8 (PCI_LIB_ADDRESS (0, 4, 0, 0x3d), 0x01);\r
49ba9447 661}\r
662\r
663\r
664VOID\r
665PlatformBdsConnectSequence (\r
666 VOID\r
667 )\r
668/*++\r
669\r
670Routine Description:\r
671\r
672 Connect with predeined platform connect sequence,\r
673 the OEM/IBV can customize with their own connect sequence.\r
674\r
675Arguments:\r
676\r
677 None.\r
678\r
679Returns:\r
680\r
681 None.\r
682\r
683--*/\r
684{\r
685 UINTN Index;\r
686\r
687 DEBUG ((EFI_D_INFO, "PlatformBdsConnectSequence\n"));\r
688\r
689 Index = 0;\r
690\r
691 //\r
692 // Here we can get the customized platform connect sequence\r
693 // Notes: we can connect with new variable which record the\r
694 // last time boots connect device path sequence\r
695 //\r
696 while (gPlatformConnectSequence[Index] != NULL) {\r
697 //\r
698 // Build the platform boot option\r
699 //\r
700 BdsLibConnectDevicePath (gPlatformConnectSequence[Index]);\r
701 Index++;\r
702 }\r
703\r
704 //\r
705 // Just use the simple policy to connect all devices\r
706 //\r
707 BdsLibConnectAll ();\r
708\r
709 PciInitialization ();\r
40f2c454 710\r
711 //\r
712 // Clear the logo after all devices are connected.\r
713 //\r
714 gST->ConOut->ClearScreen (gST->ConOut);\r
49ba9447 715}\r
716\r
717VOID\r
718PlatformBdsGetDriverOption (\r
719 IN OUT LIST_ENTRY *BdsDriverLists\r
720 )\r
721/*++\r
722\r
723Routine Description:\r
724\r
725 Load the predefined driver option, OEM/IBV can customize this\r
726 to load their own drivers\r
727\r
728Arguments:\r
729\r
730 BdsDriverLists - The header of the driver option link list.\r
731\r
732Returns:\r
733\r
734 None.\r
735\r
736--*/\r
737{\r
738 DEBUG ((EFI_D_INFO, "PlatformBdsGetDriverOption\n"));\r
739 return;\r
740}\r
741\r
742VOID\r
743PlatformBdsDiagnostics (\r
744 IN EXTENDMEM_COVERAGE_LEVEL MemoryTestLevel,\r
d18476d0 745 IN BOOLEAN QuietBoot,\r
746 IN BASEM_MEMORY_TEST BaseMemoryTest\r
49ba9447 747 )\r
748/*++\r
749\r
750Routine Description:\r
751\r
752 Perform the platform diagnostic, such like test memory. OEM/IBV also\r
753 can customize this fuction to support specific platform diagnostic.\r
754\r
755Arguments:\r
756\r
757 MemoryTestLevel - The memory test intensive level\r
758\r
759 QuietBoot - Indicate if need to enable the quiet boot\r
760\r
d18476d0 761 BaseMemoryTest - A pointer to BaseMemoryTest()\r
762\r
49ba9447 763Returns:\r
764\r
765 None.\r
766\r
767--*/\r
768{\r
769 EFI_STATUS Status;\r
770\r
771 DEBUG ((EFI_D_INFO, "PlatformBdsDiagnostics\n"));\r
772\r
773 //\r
774 // Here we can decide if we need to show\r
775 // the diagnostics screen\r
776 // Notes: this quiet boot code should be remove\r
777 // from the graphic lib\r
778 //\r
779 if (QuietBoot) {\r
d46f3632 780 EnableQuietBoot (PcdGetPtr(PcdLogoFile));\r
49ba9447 781 //\r
782 // Perform system diagnostic\r
783 //\r
d18476d0 784 Status = BaseMemoryTest (MemoryTestLevel);\r
49ba9447 785 if (EFI_ERROR (Status)) {\r
786 DisableQuietBoot ();\r
787 }\r
788\r
789 return ;\r
790 }\r
791 //\r
792 // Perform system diagnostic\r
793 //\r
d18476d0 794 Status = BaseMemoryTest (MemoryTestLevel);\r
49ba9447 795}\r
796\r
797\r
798VOID\r
799EFIAPI\r
800PlatformBdsPolicyBehavior (\r
49ba9447 801 IN OUT LIST_ENTRY *DriverOptionList,\r
d18476d0 802 IN OUT LIST_ENTRY *BootOptionList,\r
803 IN PROCESS_CAPSULES ProcessCapsules,\r
804 IN BASEM_MEMORY_TEST BaseMemoryTest\r
49ba9447 805 )\r
806/*++\r
807\r
808Routine Description:\r
809\r
810 The function will excute with as the platform policy, current policy\r
811 is driven by boot mode. IBV/OEM can customize this code for their specific\r
812 policy action.\r
813\r
814Arguments:\r
815\r
49ba9447 816 DriverOptionList - The header of the driver option link list\r
817\r
818 BootOptionList - The header of the boot option link list\r
819\r
d18476d0 820 ProcessCapsules - A pointer to ProcessCapsules()\r
821\r
822 BaseMemoryTest - A pointer to BaseMemoryTest()\r
823\r
49ba9447 824Returns:\r
825\r
826 None.\r
827\r
828--*/\r
829{\r
830 EFI_STATUS Status;\r
831 UINT16 Timeout;\r
832 EFI_EVENT UserInputDurationTime;\r
833 LIST_ENTRY *Link;\r
834 BDS_COMMON_OPTION *BootOption;\r
835 UINTN Index;\r
836 EFI_INPUT_KEY Key;\r
837 EFI_TPL OldTpl;\r
370ec7f1 838 EFI_BOOT_MODE BootMode;\r
49ba9447 839\r
840 DEBUG ((EFI_D_INFO, "PlatformBdsPolicyBehavior\n"));\r
841\r
842 //\r
843 // Init the time out value\r
844 //\r
845 Timeout = PcdGet16 (PcdPlatformBootTimeOut);\r
846\r
847 //\r
848 // Load the driver option as the driver option list\r
849 //\r
850 PlatformBdsGetDriverOption (DriverOptionList);\r
851\r
852 //\r
853 // Get current Boot Mode\r
854 //\r
370ec7f1 855 Status = BdsLibGetBootMode (&BootMode);\r
856 DEBUG ((EFI_D_ERROR, "Boot Mode:%x\n", BootMode));\r
49ba9447 857\r
858 //\r
859 // Go the different platform policy with different boot mode\r
860 // Notes: this part code can be change with the table policy\r
861 //\r
370ec7f1 862 ASSERT (BootMode == BOOT_WITH_FULL_CONFIGURATION);\r
49ba9447 863 //\r
864 // Connect platform console\r
865 //\r
866 Status = PlatformBdsConnectConsole (gPlatformConsole);\r
867 if (EFI_ERROR (Status)) {\r
868 //\r
869 // Here OEM/IBV can customize with defined action\r
870 //\r
871 PlatformBdsNoConsoleAction ();\r
872 }\r
873 //\r
874 // Create a 300ms duration event to ensure user has enough input time to enter Setup\r
875 //\r
876 Status = gBS->CreateEvent (\r
877 EVT_TIMER,\r
878 0,\r
879 NULL,\r
880 NULL,\r
881 &UserInputDurationTime\r
882 );\r
883 ASSERT (Status == EFI_SUCCESS);\r
884 Status = gBS->SetTimer (UserInputDurationTime, TimerRelative, 3000000);\r
885 ASSERT (Status == EFI_SUCCESS);\r
886 //\r
887 // Memory test and Logo show\r
888 //\r
d18476d0 889 PlatformBdsDiagnostics (IGNORE, TRUE, BaseMemoryTest);\r
49ba9447 890\r
891 //\r
892 // Perform some platform specific connect sequence\r
893 //\r
894 PlatformBdsConnectSequence ();\r
895\r
896 //\r
897 // Give one chance to enter the setup if we\r
898 // have the time out\r
899 //\r
900 if (Timeout != 0) {\r
901 //PlatformBdsEnterFrontPage (Timeout, FALSE);\r
902 }\r
903\r
904 DEBUG ((EFI_D_INFO, "BdsLibConnectAll\n"));\r
905 BdsLibConnectAll ();\r
906 BdsLibEnumerateAllBootOption (BootOptionList);\r
907\r
908 //\r
909 // Please uncomment above ConnectAll and EnumerateAll code and remove following first boot\r
910 // checking code in real production tip.\r
911 //\r
912 // In BOOT_WITH_FULL_CONFIGURATION boot mode, should always connect every device\r
913 // and do enumerate all the default boot options. But in development system board, the boot mode\r
914 // cannot be BOOT_ASSUMING_NO_CONFIGURATION_CHANGES because the machine box\r
915 // is always open. So the following code only do the ConnectAll and EnumerateAll at first boot.\r
916 //\r
917 Status = BdsLibBuildOptionFromVar (BootOptionList, L"BootOrder");\r
918 if (EFI_ERROR(Status)) {\r
919 //\r
920 // If cannot find "BootOrder" variable, it may be first boot.\r
921 // Try to connect all devices and enumerate all boot options here.\r
922 //\r
923 BdsLibConnectAll ();\r
924 BdsLibEnumerateAllBootOption (BootOptionList);\r
925 }\r
926\r
927 //\r
928 // To give the User a chance to enter Setup here, if user set TimeOut is 0.\r
929 // BDS should still give user a chance to enter Setup\r
930 //\r
931 // Connect first boot option, and then check user input before exit\r
932 //\r
933 for (Link = BootOptionList->ForwardLink; Link != BootOptionList;Link = Link->ForwardLink) {\r
934 BootOption = CR (Link, BDS_COMMON_OPTION, Link, BDS_LOAD_OPTION_SIGNATURE);\r
935 if (!IS_LOAD_OPTION_TYPE (BootOption->Attribute, LOAD_OPTION_ACTIVE)) {\r
936 //\r
937 // skip the header of the link list, becuase it has no boot option\r
938 //\r
939 continue;\r
940 } else {\r
941 //\r
942 // Make sure the boot option device path connected, but ignore the BBS device path\r
943 //\r
944 if (DevicePathType (BootOption->DevicePath) != BBS_DEVICE_PATH) {\r
945 BdsLibConnectDevicePath (BootOption->DevicePath);\r
946 }\r
947 break;\r
948 }\r
949 }\r
950\r
951 //\r
952 // Check whether the user input after the duration time has expired\r
953 //\r
954 OldTpl = EfiGetCurrentTpl();\r
955 gBS->RestoreTPL (TPL_APPLICATION);\r
956 gBS->WaitForEvent (1, &UserInputDurationTime, &Index);\r
957 gBS->CloseEvent (UserInputDurationTime);\r
958 Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);\r
959 gBS->RaiseTPL (OldTpl);\r
960\r
961 if (!EFI_ERROR (Status)) {\r
962 //\r
963 // Enter Setup if user input\r
964 //\r
965 Timeout = 0xffff;\r
966 PlatformBdsEnterFrontPage (Timeout, FALSE);\r
967 }\r
968\r
969 return ;\r
970}\r
971\r
972VOID\r
973EFIAPI\r
974PlatformBdsBootSuccess (\r
975 IN BDS_COMMON_OPTION *Option\r
976 )\r
977/*++\r
978\r
979Routine Description:\r
980\r
981 Hook point after a boot attempt succeeds. We don't expect a boot option to\r
982 return, so the EFI 1.0 specification defines that you will default to an\r
983 interactive mode and stop processing the BootOrder list in this case. This\r
984 is alos a platform implementation and can be customized by IBV/OEM.\r
985\r
986Arguments:\r
987\r
988 Option - Pointer to Boot Option that succeeded to boot.\r
989\r
990Returns:\r
991\r
992 None.\r
993\r
994--*/\r
995{\r
996 CHAR16 *TmpStr;\r
997\r
998 DEBUG ((EFI_D_INFO, "PlatformBdsBootSuccess\n"));\r
999 //\r
1000 // If Boot returned with EFI_SUCCESS and there is not in the boot device\r
1001 // select loop then we need to pop up a UI and wait for user input.\r
1002 //\r
1003 TmpStr = Option->StatusString;\r
1004 if (TmpStr != NULL) {\r
1005 BdsLibOutputStrings (gST->ConOut, TmpStr, Option->Description, L"\n\r", NULL);\r
1006 FreePool (TmpStr);\r
1007 }\r
1008}\r
1009\r
1010VOID\r
1011EFIAPI\r
1012PlatformBdsBootFail (\r
1013 IN BDS_COMMON_OPTION *Option,\r
1014 IN EFI_STATUS Status,\r
1015 IN CHAR16 *ExitData,\r
1016 IN UINTN ExitDataSize\r
1017 )\r
1018/*++\r
1019\r
1020Routine Description:\r
1021\r
1022 Hook point after a boot attempt fails.\r
1023\r
1024Arguments:\r
1025\r
1026 Option - Pointer to Boot Option that failed to boot.\r
1027\r
1028 Status - Status returned from failed boot.\r
1029\r
1030 ExitData - Exit data returned from failed boot.\r
1031\r
1032 ExitDataSize - Exit data size returned from failed boot.\r
1033\r
1034Returns:\r
1035\r
1036 None.\r
1037\r
1038--*/\r
1039{\r
1040 CHAR16 *TmpStr;\r
1041\r
1042 DEBUG ((EFI_D_INFO, "PlatformBdsBootFail\n"));\r
1043\r
1044 //\r
1045 // If Boot returned with failed status then we need to pop up a UI and wait\r
1046 // for user input.\r
1047 //\r
1048 TmpStr = Option->StatusString;\r
1049 if (TmpStr != NULL) {\r
1050 BdsLibOutputStrings (gST->ConOut, TmpStr, Option->Description, L"\n\r", NULL);\r
1051 FreePool (TmpStr);\r
1052 }\r
1053}\r
1054\r
1055EFI_STATUS\r
1056PlatformBdsNoConsoleAction (\r
1057 VOID\r
1058 )\r
1059/*++\r
1060\r
1061Routine Description:\r
1062\r
1063 This function is remained for IBV/OEM to do some platform action,\r
1064 if there no console device can be connected.\r
1065\r
1066Arguments:\r
1067\r
1068 None.\r
1069\r
1070Returns:\r
1071\r
1072 EFI_SUCCESS - Direct return success now.\r
1073\r
1074--*/\r
1075{\r
1076 DEBUG ((EFI_D_INFO, "PlatformBdsNoConsoleAction\n"));\r
1077 return EFI_SUCCESS;\r
1078}\r
1079\r
24cdd14e 1080VOID\r
49ba9447 1081EFIAPI\r
1082PlatformBdsLockNonUpdatableFlash (\r
1083 VOID\r
1084 )\r
1085{\r
1086 DEBUG ((EFI_D_INFO, "PlatformBdsLockNonUpdatableFlash\n"));\r
24cdd14e 1087 return;\r
49ba9447 1088}\r
40f2c454 1089\r
1090\r
1091/**\r
1092 This notification function is invoked when an instance of the\r
1093 EFI_DEVICE_PATH_PROTOCOL is produced.\r
1094\r
1095 @param Event The event that occured\r
1096 @param Context For EFI compatiblity. Not used.\r
1097\r
1098**/\r
1099VOID\r
1100EFIAPI\r
1101NotifyDevPath (\r
1102 IN EFI_EVENT Event,\r
1103 IN VOID *Context\r
1104 )\r
1105{\r
1106 EFI_HANDLE Handle;\r
1107 EFI_STATUS Status;\r
1108 UINTN BufferSize;\r
1109 EFI_DEVICE_PATH_PROTOCOL *DevPathNode;\r
1110 ATAPI_DEVICE_PATH *Atapi;\r
1111\r
1112 //\r
1113 // Examine all new handles\r
1114 //\r
1115 for (;;) {\r
1116 //\r
1117 // Get the next handle\r
1118 //\r
1119 BufferSize = sizeof (Handle);\r
1120 Status = gBS->LocateHandle (\r
1121 ByRegisterNotify,\r
1122 NULL,\r
1123 mEfiDevPathNotifyReg,\r
1124 &BufferSize,\r
1125 &Handle\r
1126 );\r
1127\r
1128 //\r
1129 // If not found, we're done\r
1130 //\r
1131 if (EFI_NOT_FOUND == Status) {\r
1132 break;\r
1133 }\r
1134\r
1135 if (EFI_ERROR (Status)) {\r
1136 continue;\r
1137 }\r
1138\r
1139 //\r
1140 // Get the DevicePath protocol on that handle\r
1141 //\r
1142 Status = gBS->HandleProtocol (Handle, &gEfiDevicePathProtocolGuid, (VOID **)&DevPathNode);\r
1143 ASSERT_EFI_ERROR (Status);\r
1144\r
1145 while (!IsDevicePathEnd (DevPathNode)) {\r
1146 //\r
1147 // Find the handler to dump this device path node\r
1148 //\r
1149 if (\r
1150 (DevicePathType(DevPathNode) == MESSAGING_DEVICE_PATH) &&\r
1151 (DevicePathSubType(DevPathNode) == MSG_ATAPI_DP)\r
1152 ) {\r
1153 Atapi = (ATAPI_DEVICE_PATH*) DevPathNode;\r
1154 PciOr16 (\r
1155 PCI_LIB_ADDRESS (\r
1156 0,\r
1157 1,\r
1158 1,\r
1159 (Atapi->PrimarySecondary == 1) ? 0x42: 0x40\r
1160 ),\r
1161 BIT15\r
1162 );\r
1163 }\r
1164\r
1165 //\r
1166 // Next device path node\r
1167 //\r
1168 DevPathNode = NextDevicePathNode (DevPathNode);\r
1169 }\r
1170 }\r
1171\r
1172 return;\r
1173}\r
1174\r
1175\r
1176VOID\r
1177InstallDevicePathCallback (\r
1178 VOID\r
1179 )\r
1180{\r
1181 DEBUG ((EFI_D_INFO, "Registered NotifyDevPath Event\n"));\r
1182 mEfiDevPathEvent = EfiCreateProtocolNotifyEvent (\r
1183 &gEfiDevicePathProtocolGuid,\r
1184 TPL_CALLBACK,\r
1185 NotifyDevPath,\r
1186 NULL,\r
1187 &mEfiDevPathNotifyReg\r
1188 );\r
1189}\r
1190\r
24cdd14e
LG
1191/**\r
1192 Lock the ConsoleIn device in system table. All key\r
1193 presses will be ignored until the Password is typed in. The only way to\r
1194 disable the password is to type it in to a ConIn device.\r
1195\r
1196 @param Password Password used to lock ConIn device.\r
1197\r
1198 @retval EFI_SUCCESS lock the Console In Spliter virtual handle successfully.\r
1199 @retval EFI_UNSUPPORTED Password not found\r
1200\r
1201**/\r
1202EFI_STATUS\r
1203EFIAPI\r
1204LockKeyboards (\r
1205 IN CHAR16 *Password\r
1206 )\r
1207{\r
1208 return EFI_UNSUPPORTED;\r
1209}\r
5106d422 1210\r
1211\r
1212STATIC\r
1213VOID\r
1214LoadVideoRom (\r
ccd4b7da 1215 VOID\r
5106d422 1216 )\r
1217{\r
1218 PCI_DATA_STRUCTURE *Pcir;\r
1219 UINTN RomSize;\r
1220\r
1221 //\r
1222 // The virtual machines sometimes load the video rom image\r
1223 // directly at the legacy video BIOS location of C000:0000,\r
1224 // and do not implement the PCI expansion ROM feature.\r
1225 //\r
1226 Pcir = (PCI_DATA_STRUCTURE *) (UINTN) 0xc0000;\r
1227 RomSize = Pcir->ImageLength * 512;\r
1228 PciRomLoadEfiDriversFromRomImage (0xc0000, RomSize);\r
1229}\r
1230\r
1231\r
1232STATIC\r
1233EFI_STATUS\r
1234PciRomLoadEfiDriversFromRomImage (\r
1235 IN EFI_PHYSICAL_ADDRESS Rom,\r
1236 IN UINTN RomSize\r
1237 )\r
1238{\r
1239 CHAR16 *FileName;\r
1240 EFI_PCI_EXPANSION_ROM_HEADER *EfiRomHeader;\r
1241 PCI_DATA_STRUCTURE *Pcir;\r
1242 UINTN ImageIndex;\r
1243 UINTN RomOffset;\r
1244 UINT32 ImageSize;\r
1245 UINT16 ImageOffset;\r
1246 EFI_HANDLE ImageHandle;\r
1247 EFI_STATUS Status;\r
1248 EFI_STATUS retStatus;\r
1249 EFI_DEVICE_PATH_PROTOCOL *FilePath;\r
1250 BOOLEAN SkipImage;\r
1251 UINT32 DestinationSize;\r
1252 UINT32 ScratchSize;\r
1253 UINT8 *Scratch;\r
1254 VOID *ImageBuffer;\r
1255 VOID *DecompressedImageBuffer;\r
1256 UINT32 ImageLength;\r
1257 EFI_DECOMPRESS_PROTOCOL *Decompress;\r
1258\r
1259 FileName = L"PciRomInMemory";\r
1260\r
1261 //FileName = L"PciRom Addr=0000000000000000";\r
1262 //HexToString (&FileName[12], Rom, 16);\r
1263\r
1264 ImageIndex = 0;\r
1265 retStatus = EFI_NOT_FOUND;\r
1266 RomOffset = (UINTN) Rom;\r
1267\r
1268 do {\r
1269\r
1270 EfiRomHeader = (EFI_PCI_EXPANSION_ROM_HEADER *) (UINTN) RomOffset;\r
1271\r
1272 if (EfiRomHeader->Signature != 0xaa55) {\r
1273 return retStatus;\r
1274 }\r
1275\r
1276 Pcir = (PCI_DATA_STRUCTURE *) (UINTN) (RomOffset + EfiRomHeader->PcirOffset);\r
1277 ImageSize = Pcir->ImageLength * 512;\r
1278\r
1279 if ((Pcir->CodeType == PCI_CODE_TYPE_EFI_IMAGE) &&\r
1280 (EfiRomHeader->EfiSignature == EFI_PCI_EXPANSION_ROM_HEADER_EFISIGNATURE) ) {\r
1281\r
1282 if ((EfiRomHeader->EfiSubsystem == EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER) ||\r
1283 (EfiRomHeader->EfiSubsystem == EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER) ) {\r
1284\r
1285 ImageOffset = EfiRomHeader->EfiImageHeaderOffset;\r
1286 ImageSize = EfiRomHeader->InitializationSize * 512;\r
1287\r
1288 ImageBuffer = (VOID *) (UINTN) (RomOffset + ImageOffset);\r
1289 ImageLength = ImageSize - ImageOffset;\r
1290 DecompressedImageBuffer = NULL;\r
1291\r
1292 //\r
1293 // decompress here if needed\r
1294 //\r
1295 SkipImage = FALSE;\r
1296 if (EfiRomHeader->CompressionType > EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED) {\r
1297 SkipImage = TRUE;\r
1298 }\r
1299\r
1300 if (EfiRomHeader->CompressionType == EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED) {\r
1301 Status = gBS->LocateProtocol (&gEfiDecompressProtocolGuid, NULL, (VOID **) &Decompress);\r
1302 if (EFI_ERROR (Status)) {\r
1303 SkipImage = TRUE;\r
1304 } else {\r
1305 SkipImage = TRUE;\r
1306 Status = Decompress->GetInfo (\r
1307 Decompress,\r
1308 ImageBuffer,\r
1309 ImageLength,\r
1310 &DestinationSize,\r
1311 &ScratchSize\r
1312 );\r
1313 if (!EFI_ERROR (Status)) {\r
1314 DecompressedImageBuffer = NULL;\r
1315 DecompressedImageBuffer = AllocatePool (DestinationSize);\r
1316 if (DecompressedImageBuffer != NULL) {\r
1317 Scratch = AllocatePool (ScratchSize);\r
1318 if (Scratch != NULL) {\r
1319 Status = Decompress->Decompress (\r
1320 Decompress,\r
1321 ImageBuffer,\r
1322 ImageLength,\r
1323 DecompressedImageBuffer,\r
1324 DestinationSize,\r
1325 Scratch,\r
1326 ScratchSize\r
1327 );\r
1328 if (!EFI_ERROR (Status)) {\r
1329 ImageBuffer = DecompressedImageBuffer;\r
1330 ImageLength = DestinationSize;\r
1331 SkipImage = FALSE;\r
1332 }\r
1333\r
1334 gBS->FreePool (Scratch);\r
1335 }\r
1336 }\r
1337 }\r
1338 }\r
1339 }\r
1340\r
1341 if (!SkipImage) {\r
1342\r
1343 //\r
1344 // load image and start image\r
1345 //\r
1346\r
1347 FilePath = FileDevicePath (NULL, FileName);\r
1348\r
1349 Status = gBS->LoadImage (\r
1350 FALSE,\r
1351 gImageHandle,\r
1352 FilePath,\r
1353 ImageBuffer,\r
1354 ImageLength,\r
1355 &ImageHandle\r
1356 );\r
1357 if (!EFI_ERROR (Status)) {\r
1358 Status = gBS->StartImage (ImageHandle, NULL, NULL);\r
1359 if (!EFI_ERROR (Status)) {\r
1360 retStatus = Status;\r
1361 }\r
1362 }\r
1363 if (FilePath != NULL) {\r
1364 gBS->FreePool (FilePath);\r
1365 }\r
1366 }\r
1367\r
1368 if (DecompressedImageBuffer != NULL) {\r
1369 gBS->FreePool (DecompressedImageBuffer);\r
1370 }\r
1371\r
1372 }\r
1373 }\r
1374\r
1375 RomOffset = RomOffset + ImageSize;\r
1376 ImageIndex++;\r
1377 } while (((Pcir->Indicator & 0x80) == 0x00) && ((RomOffset - (UINTN) Rom) < RomSize));\r
1378\r
1379 return retStatus;\r
1380}\r
1381\r
1382\r