]> git.proxmox.com Git - mirror_edk2.git/blame - OvmfPkg/Library/PlatformBdsLib/BdsPlatform.c
OVMF: Add support for more persistent NV variables which can survive a system reboot.
[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
465 if (!DetectVgaOnly) {\r
466 //\r
467 // Here we decide whether it is LPC Bridge\r
468 //\r
469 if ((IS_PCI_LPC (&Pci)) ||\r
470 ((IS_PCI_ISA_PDECODE (&Pci)) &&\r
471 (Pci.Hdr.VendorId == 0x8086) &&\r
472 (Pci.Hdr.DeviceId == 0x7000)\r
473 )\r
474 ) {\r
475 Status = PciIo->Attributes (\r
476 PciIo,\r
477 EfiPciIoAttributeOperationEnable,\r
478 EFI_PCI_DEVICE_ENABLE,\r
479 NULL\r
480 );\r
481 //\r
482 // Add IsaKeyboard to ConIn,\r
483 // add IsaSerial to ConOut, ConIn, ErrOut\r
484 //\r
485 DEBUG ((EFI_D_INFO, "Find the LPC Bridge device\n"));\r
486 PrepareLpcBridgeDevicePath (HandleBuffer[Index]);\r
487 continue;\r
488 }\r
489 //\r
490 // Here we decide which Serial device to enable in PCI bus\r
491 //\r
492 if (IS_PCI_16550SERIAL (&Pci)) {\r
493 //\r
494 // Add them to ConOut, ConIn, ErrOut.\r
495 //\r
496 DEBUG ((EFI_D_INFO, "Find the 16550 SERIAL device\n"));\r
497 PreparePciSerialDevicePath (HandleBuffer[Index]);\r
498 continue;\r
499 }\r
500 }\r
501\r
502 if ((Pci.Hdr.VendorId == 0x8086) &&\r
503 (Pci.Hdr.DeviceId == 0x7010)\r
504 ) {\r
505 Status = PciIo->Attributes (\r
506 PciIo,\r
507 EfiPciIoAttributeOperationEnable,\r
508 EFI_PCI_DEVICE_ENABLE,\r
509 NULL\r
510 );\r
511 }\r
512\r
513 //\r
514 // Here we decide which VGA device to enable in PCI bus\r
515 //\r
516 if (IS_PCI_VGA (&Pci)) {\r
517 //\r
518 // Add them to ConOut.\r
519 //\r
520 DEBUG ((EFI_D_INFO, "Find the VGA device\n"));\r
521 PreparePciVgaDevicePath (HandleBuffer[Index]);\r
522 continue;\r
523 }\r
524 }\r
525\r
526 gBS->FreePool (HandleBuffer);\r
527\r
528 return EFI_SUCCESS;\r
529}\r
530\r
531\r
532EFI_STATUS\r
533PlatformBdsConnectConsole (\r
534 IN BDS_CONSOLE_CONNECT_ENTRY *PlatformConsole\r
535 )\r
536/*++\r
537\r
538Routine Description:\r
539\r
540 Connect the predefined platform default console device. Always try to find\r
541 and enable the vga device if have.\r
542\r
543Arguments:\r
544\r
545 PlatformConsole - Predfined platform default console device array.\r
546\r
547Returns:\r
548\r
549 EFI_SUCCESS - Success connect at least one ConIn and ConOut\r
550 device, there must have one ConOut device is\r
551 active vga device.\r
552\r
553 EFI_STATUS - Return the status of\r
554 BdsLibConnectAllDefaultConsoles ()\r
555\r
556--*/\r
557{\r
558 EFI_STATUS Status;\r
559 UINTN Index;\r
560 EFI_DEVICE_PATH_PROTOCOL *VarConout;\r
561 EFI_DEVICE_PATH_PROTOCOL *VarConin;\r
562 UINTN DevicePathSize;\r
563\r
564 //\r
565 // Connect RootBridge\r
566 //\r
567 ConnectRootBridge ();\r
568\r
569 VarConout = BdsLibGetVariableAndSize (\r
570 VarConsoleOut,\r
571 &gEfiGlobalVariableGuid,\r
572 &DevicePathSize\r
573 );\r
574 VarConin = BdsLibGetVariableAndSize (\r
575 VarConsoleInp,\r
576 &gEfiGlobalVariableGuid,\r
577 &DevicePathSize\r
578 );\r
579\r
580 if (VarConout == NULL || VarConin == NULL) {\r
581 //\r
582 // Do platform specific PCI Device check and add them to ConOut, ConIn, ErrOut\r
583 //\r
584 DetectAndPreparePlatformPciDevicePath (FALSE);\r
585\r
586 //\r
587 // Have chance to connect the platform default console,\r
588 // the platform default console is the minimue device group\r
589 // the platform should support\r
590 //\r
591 for (Index = 0; PlatformConsole[Index].DevicePath != NULL; ++Index) {\r
592 //\r
593 // Update the console variable with the connect type\r
594 //\r
595 if ((PlatformConsole[Index].ConnectType & CONSOLE_IN) == CONSOLE_IN) {\r
596 BdsLibUpdateConsoleVariable (VarConsoleInp, PlatformConsole[Index].DevicePath, NULL);\r
597 }\r
598 if ((PlatformConsole[Index].ConnectType & CONSOLE_OUT) == CONSOLE_OUT) {\r
599 BdsLibUpdateConsoleVariable (VarConsoleOut, PlatformConsole[Index].DevicePath, NULL);\r
600 }\r
601 if ((PlatformConsole[Index].ConnectType & STD_ERROR) == STD_ERROR) {\r
602 BdsLibUpdateConsoleVariable (VarErrorOut, PlatformConsole[Index].DevicePath, NULL);\r
603 }\r
604 }\r
605 } else {\r
606 //\r
607 // Only detect VGA device and add them to ConOut\r
608 //\r
609 DetectAndPreparePlatformPciDevicePath (TRUE);\r
610 }\r
611\r
612 //\r
613 // Connect the all the default console with current cosole variable\r
614 //\r
615 Status = BdsLibConnectAllDefaultConsoles ();\r
616 if (EFI_ERROR (Status)) {\r
617 return Status;\r
618 }\r
619\r
620 return EFI_SUCCESS;\r
621}\r
622\r
623\r
624VOID\r
625PciInitialization (\r
626 )\r
627{\r
628 //\r
40f2c454 629 // Bus 0, Device 0, Function 0 - Host to PCI Bridge\r
630 //\r
631 PciWrite8 (PCI_LIB_ADDRESS (0, 0, 0, 0x3c), 0x00);\r
632\r
633 //\r
634 // Bus 0, Device 1, Function 0 - PCI to ISA Bridge\r
49ba9447 635 //\r
40f2c454 636 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x3c), 0x00);\r
637 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x60), 0x0b);\r
638 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x61), 0x09);\r
639 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x62), 0x0b);\r
640 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x63), 0x09);\r
49ba9447 641\r
642 //\r
40f2c454 643 // Bus 0, Device 1, Function 1 - IDE Controller\r
49ba9447 644 //\r
40f2c454 645 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 1, 0x3c), 0x00);\r
646 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 1, 0x0d), 0x40);\r
49ba9447 647\r
648 //\r
40f2c454 649 // Bus 0, Device 1, Function 3 - Power Managment Controller\r
49ba9447 650 //\r
40f2c454 651 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 3, 0x3c), 0x0b);\r
652 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 3, 0x3d), 0x01);\r
49ba9447 653\r
654 //\r
40f2c454 655 // Bus 0, Device 2, Function 0 - Video Controller\r
49ba9447 656 //\r
40f2c454 657 PciWrite8 (PCI_LIB_ADDRESS (0, 2, 0, 0x3c), 0x00);\r
49ba9447 658\r
659 //\r
40f2c454 660 // Bus 0, Device 3, Function 0 - Network Controller\r
49ba9447 661 //\r
40f2c454 662 PciWrite8 (PCI_LIB_ADDRESS (0, 3, 0, 0x3c), 0x0b);\r
663 PciWrite8 (PCI_LIB_ADDRESS (0, 3, 0, 0x3d), 0x01);\r
49ba9447 664\r
665 //\r
40f2c454 666 // Bus 0, Device 4, Function 0 - RAM Memory\r
49ba9447 667 //\r
40f2c454 668 PciWrite8 (PCI_LIB_ADDRESS (0, 4, 0, 0x3c), 0x09);\r
669 PciWrite8 (PCI_LIB_ADDRESS (0, 4, 0, 0x3d), 0x01);\r
49ba9447 670}\r
671\r
672\r
673VOID\r
674PlatformBdsConnectSequence (\r
675 VOID\r
676 )\r
677/*++\r
678\r
679Routine Description:\r
680\r
681 Connect with predeined platform connect sequence,\r
682 the OEM/IBV can customize with their own connect sequence.\r
683\r
684Arguments:\r
685\r
686 None.\r
687\r
688Returns:\r
689\r
690 None.\r
691\r
692--*/\r
693{\r
694 UINTN Index;\r
695\r
696 DEBUG ((EFI_D_INFO, "PlatformBdsConnectSequence\n"));\r
697\r
698 Index = 0;\r
699\r
700 //\r
701 // Here we can get the customized platform connect sequence\r
702 // Notes: we can connect with new variable which record the\r
703 // last time boots connect device path sequence\r
704 //\r
705 while (gPlatformConnectSequence[Index] != NULL) {\r
706 //\r
707 // Build the platform boot option\r
708 //\r
709 BdsLibConnectDevicePath (gPlatformConnectSequence[Index]);\r
710 Index++;\r
711 }\r
712\r
713 //\r
714 // Just use the simple policy to connect all devices\r
715 //\r
716 BdsLibConnectAll ();\r
717\r
718 PciInitialization ();\r
40f2c454 719\r
720 //\r
721 // Clear the logo after all devices are connected.\r
722 //\r
723 gST->ConOut->ClearScreen (gST->ConOut);\r
49ba9447 724}\r
725\r
726VOID\r
727PlatformBdsGetDriverOption (\r
728 IN OUT LIST_ENTRY *BdsDriverLists\r
729 )\r
730/*++\r
731\r
732Routine Description:\r
733\r
734 Load the predefined driver option, OEM/IBV can customize this\r
735 to load their own drivers\r
736\r
737Arguments:\r
738\r
739 BdsDriverLists - The header of the driver option link list.\r
740\r
741Returns:\r
742\r
743 None.\r
744\r
745--*/\r
746{\r
747 DEBUG ((EFI_D_INFO, "PlatformBdsGetDriverOption\n"));\r
748 return;\r
749}\r
750\r
751VOID\r
752PlatformBdsDiagnostics (\r
753 IN EXTENDMEM_COVERAGE_LEVEL MemoryTestLevel,\r
d18476d0 754 IN BOOLEAN QuietBoot,\r
755 IN BASEM_MEMORY_TEST BaseMemoryTest\r
49ba9447 756 )\r
757/*++\r
758\r
759Routine Description:\r
760\r
761 Perform the platform diagnostic, such like test memory. OEM/IBV also\r
762 can customize this fuction to support specific platform diagnostic.\r
763\r
764Arguments:\r
765\r
766 MemoryTestLevel - The memory test intensive level\r
767\r
768 QuietBoot - Indicate if need to enable the quiet boot\r
769\r
d18476d0 770 BaseMemoryTest - A pointer to BaseMemoryTest()\r
771\r
49ba9447 772Returns:\r
773\r
774 None.\r
775\r
776--*/\r
777{\r
778 EFI_STATUS Status;\r
779\r
780 DEBUG ((EFI_D_INFO, "PlatformBdsDiagnostics\n"));\r
781\r
782 //\r
783 // Here we can decide if we need to show\r
784 // the diagnostics screen\r
785 // Notes: this quiet boot code should be remove\r
786 // from the graphic lib\r
787 //\r
788 if (QuietBoot) {\r
d46f3632 789 EnableQuietBoot (PcdGetPtr(PcdLogoFile));\r
49ba9447 790 //\r
791 // Perform system diagnostic\r
792 //\r
d18476d0 793 Status = BaseMemoryTest (MemoryTestLevel);\r
49ba9447 794 if (EFI_ERROR (Status)) {\r
795 DisableQuietBoot ();\r
796 }\r
797\r
798 return ;\r
799 }\r
800 //\r
801 // Perform system diagnostic\r
802 //\r
d18476d0 803 Status = BaseMemoryTest (MemoryTestLevel);\r
49ba9447 804}\r
805\r
806\r
807VOID\r
808EFIAPI\r
809PlatformBdsPolicyBehavior (\r
49ba9447 810 IN OUT LIST_ENTRY *DriverOptionList,\r
d18476d0 811 IN OUT LIST_ENTRY *BootOptionList,\r
812 IN PROCESS_CAPSULES ProcessCapsules,\r
813 IN BASEM_MEMORY_TEST BaseMemoryTest\r
49ba9447 814 )\r
815/*++\r
816\r
817Routine Description:\r
818\r
819 The function will excute with as the platform policy, current policy\r
820 is driven by boot mode. IBV/OEM can customize this code for their specific\r
821 policy action.\r
822\r
823Arguments:\r
824\r
49ba9447 825 DriverOptionList - The header of the driver option link list\r
826\r
827 BootOptionList - The header of the boot option link list\r
828\r
d18476d0 829 ProcessCapsules - A pointer to ProcessCapsules()\r
830\r
831 BaseMemoryTest - A pointer to BaseMemoryTest()\r
832\r
49ba9447 833Returns:\r
834\r
835 None.\r
836\r
837--*/\r
838{\r
839 EFI_STATUS Status;\r
840 UINT16 Timeout;\r
841 EFI_EVENT UserInputDurationTime;\r
842 LIST_ENTRY *Link;\r
843 BDS_COMMON_OPTION *BootOption;\r
844 UINTN Index;\r
845 EFI_INPUT_KEY Key;\r
846 EFI_TPL OldTpl;\r
370ec7f1 847 EFI_BOOT_MODE BootMode;\r
49ba9447 848\r
849 DEBUG ((EFI_D_INFO, "PlatformBdsPolicyBehavior\n"));\r
850\r
851 //\r
852 // Init the time out value\r
853 //\r
854 Timeout = PcdGet16 (PcdPlatformBootTimeOut);\r
855\r
856 //\r
857 // Load the driver option as the driver option list\r
858 //\r
859 PlatformBdsGetDriverOption (DriverOptionList);\r
860\r
861 //\r
862 // Get current Boot Mode\r
863 //\r
370ec7f1 864 Status = BdsLibGetBootMode (&BootMode);\r
865 DEBUG ((EFI_D_ERROR, "Boot Mode:%x\n", BootMode));\r
49ba9447 866\r
867 //\r
868 // Go the different platform policy with different boot mode\r
869 // Notes: this part code can be change with the table policy\r
870 //\r
370ec7f1 871 ASSERT (BootMode == BOOT_WITH_FULL_CONFIGURATION);\r
49ba9447 872 //\r
873 // Connect platform console\r
874 //\r
875 Status = PlatformBdsConnectConsole (gPlatformConsole);\r
876 if (EFI_ERROR (Status)) {\r
877 //\r
878 // Here OEM/IBV can customize with defined action\r
879 //\r
880 PlatformBdsNoConsoleAction ();\r
881 }\r
882 //\r
883 // Create a 300ms duration event to ensure user has enough input time to enter Setup\r
884 //\r
885 Status = gBS->CreateEvent (\r
886 EVT_TIMER,\r
887 0,\r
888 NULL,\r
889 NULL,\r
890 &UserInputDurationTime\r
891 );\r
892 ASSERT (Status == EFI_SUCCESS);\r
893 Status = gBS->SetTimer (UserInputDurationTime, TimerRelative, 3000000);\r
894 ASSERT (Status == EFI_SUCCESS);\r
895 //\r
896 // Memory test and Logo show\r
897 //\r
d18476d0 898 PlatformBdsDiagnostics (IGNORE, TRUE, BaseMemoryTest);\r
49ba9447 899\r
900 //\r
901 // Perform some platform specific connect sequence\r
902 //\r
903 PlatformBdsConnectSequence ();\r
904\r
905 //\r
906 // Give one chance to enter the setup if we\r
907 // have the time out\r
908 //\r
909 if (Timeout != 0) {\r
910 //PlatformBdsEnterFrontPage (Timeout, FALSE);\r
911 }\r
912\r
913 DEBUG ((EFI_D_INFO, "BdsLibConnectAll\n"));\r
914 BdsLibConnectAll ();\r
915 BdsLibEnumerateAllBootOption (BootOptionList);\r
916\r
917 //\r
918 // Please uncomment above ConnectAll and EnumerateAll code and remove following first boot\r
919 // checking code in real production tip.\r
920 //\r
921 // In BOOT_WITH_FULL_CONFIGURATION boot mode, should always connect every device\r
922 // and do enumerate all the default boot options. But in development system board, the boot mode\r
923 // cannot be BOOT_ASSUMING_NO_CONFIGURATION_CHANGES because the machine box\r
924 // is always open. So the following code only do the ConnectAll and EnumerateAll at first boot.\r
925 //\r
926 Status = BdsLibBuildOptionFromVar (BootOptionList, L"BootOrder");\r
927 if (EFI_ERROR(Status)) {\r
928 //\r
929 // If cannot find "BootOrder" variable, it may be first boot.\r
930 // Try to connect all devices and enumerate all boot options here.\r
931 //\r
932 BdsLibConnectAll ();\r
933 BdsLibEnumerateAllBootOption (BootOptionList);\r
934 }\r
935\r
936 //\r
937 // To give the User a chance to enter Setup here, if user set TimeOut is 0.\r
938 // BDS should still give user a chance to enter Setup\r
939 //\r
940 // Connect first boot option, and then check user input before exit\r
941 //\r
942 for (Link = BootOptionList->ForwardLink; Link != BootOptionList;Link = Link->ForwardLink) {\r
943 BootOption = CR (Link, BDS_COMMON_OPTION, Link, BDS_LOAD_OPTION_SIGNATURE);\r
944 if (!IS_LOAD_OPTION_TYPE (BootOption->Attribute, LOAD_OPTION_ACTIVE)) {\r
945 //\r
946 // skip the header of the link list, becuase it has no boot option\r
947 //\r
948 continue;\r
949 } else {\r
950 //\r
951 // Make sure the boot option device path connected, but ignore the BBS device path\r
952 //\r
953 if (DevicePathType (BootOption->DevicePath) != BBS_DEVICE_PATH) {\r
954 BdsLibConnectDevicePath (BootOption->DevicePath);\r
955 }\r
956 break;\r
957 }\r
958 }\r
959\r
960 //\r
961 // Check whether the user input after the duration time has expired\r
962 //\r
963 OldTpl = EfiGetCurrentTpl();\r
964 gBS->RestoreTPL (TPL_APPLICATION);\r
965 gBS->WaitForEvent (1, &UserInputDurationTime, &Index);\r
966 gBS->CloseEvent (UserInputDurationTime);\r
967 Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);\r
968 gBS->RaiseTPL (OldTpl);\r
969\r
970 if (!EFI_ERROR (Status)) {\r
971 //\r
972 // Enter Setup if user input\r
973 //\r
974 Timeout = 0xffff;\r
975 PlatformBdsEnterFrontPage (Timeout, FALSE);\r
976 }\r
977\r
978 return ;\r
979}\r
980\r
981VOID\r
982EFIAPI\r
983PlatformBdsBootSuccess (\r
984 IN BDS_COMMON_OPTION *Option\r
985 )\r
986/*++\r
987\r
988Routine Description:\r
989\r
990 Hook point after a boot attempt succeeds. We don't expect a boot option to\r
991 return, so the EFI 1.0 specification defines that you will default to an\r
992 interactive mode and stop processing the BootOrder list in this case. This\r
993 is alos a platform implementation and can be customized by IBV/OEM.\r
994\r
995Arguments:\r
996\r
997 Option - Pointer to Boot Option that succeeded to boot.\r
998\r
999Returns:\r
1000\r
1001 None.\r
1002\r
1003--*/\r
1004{\r
1005 CHAR16 *TmpStr;\r
1006\r
1007 DEBUG ((EFI_D_INFO, "PlatformBdsBootSuccess\n"));\r
1008 //\r
1009 // If Boot returned with EFI_SUCCESS and there is not in the boot device\r
1010 // select loop then we need to pop up a UI and wait for user input.\r
1011 //\r
1012 TmpStr = Option->StatusString;\r
1013 if (TmpStr != NULL) {\r
1014 BdsLibOutputStrings (gST->ConOut, TmpStr, Option->Description, L"\n\r", NULL);\r
1015 FreePool (TmpStr);\r
1016 }\r
1017}\r
1018\r
1019VOID\r
1020EFIAPI\r
1021PlatformBdsBootFail (\r
1022 IN BDS_COMMON_OPTION *Option,\r
1023 IN EFI_STATUS Status,\r
1024 IN CHAR16 *ExitData,\r
1025 IN UINTN ExitDataSize\r
1026 )\r
1027/*++\r
1028\r
1029Routine Description:\r
1030\r
1031 Hook point after a boot attempt fails.\r
1032\r
1033Arguments:\r
1034\r
1035 Option - Pointer to Boot Option that failed to boot.\r
1036\r
1037 Status - Status returned from failed boot.\r
1038\r
1039 ExitData - Exit data returned from failed boot.\r
1040\r
1041 ExitDataSize - Exit data size returned from failed boot.\r
1042\r
1043Returns:\r
1044\r
1045 None.\r
1046\r
1047--*/\r
1048{\r
1049 CHAR16 *TmpStr;\r
1050\r
1051 DEBUG ((EFI_D_INFO, "PlatformBdsBootFail\n"));\r
1052\r
1053 //\r
1054 // If Boot returned with failed status then we need to pop up a UI and wait\r
1055 // for user input.\r
1056 //\r
1057 TmpStr = Option->StatusString;\r
1058 if (TmpStr != NULL) {\r
1059 BdsLibOutputStrings (gST->ConOut, TmpStr, Option->Description, L"\n\r", NULL);\r
1060 FreePool (TmpStr);\r
1061 }\r
1062}\r
1063\r
1064EFI_STATUS\r
1065PlatformBdsNoConsoleAction (\r
1066 VOID\r
1067 )\r
1068/*++\r
1069\r
1070Routine Description:\r
1071\r
1072 This function is remained for IBV/OEM to do some platform action,\r
1073 if there no console device can be connected.\r
1074\r
1075Arguments:\r
1076\r
1077 None.\r
1078\r
1079Returns:\r
1080\r
1081 EFI_SUCCESS - Direct return success now.\r
1082\r
1083--*/\r
1084{\r
1085 DEBUG ((EFI_D_INFO, "PlatformBdsNoConsoleAction\n"));\r
1086 return EFI_SUCCESS;\r
1087}\r
1088\r
24cdd14e 1089VOID\r
49ba9447 1090EFIAPI\r
1091PlatformBdsLockNonUpdatableFlash (\r
1092 VOID\r
1093 )\r
1094{\r
1095 DEBUG ((EFI_D_INFO, "PlatformBdsLockNonUpdatableFlash\n"));\r
24cdd14e 1096 return;\r
49ba9447 1097}\r
40f2c454 1098\r
1099\r
1100/**\r
1101 This notification function is invoked when an instance of the\r
1102 EFI_DEVICE_PATH_PROTOCOL is produced.\r
1103\r
1104 @param Event The event that occured\r
1105 @param Context For EFI compatiblity. Not used.\r
1106\r
1107**/\r
1108VOID\r
1109EFIAPI\r
1110NotifyDevPath (\r
1111 IN EFI_EVENT Event,\r
1112 IN VOID *Context\r
1113 )\r
1114{\r
1115 EFI_HANDLE Handle;\r
1116 EFI_STATUS Status;\r
1117 UINTN BufferSize;\r
1118 EFI_DEVICE_PATH_PROTOCOL *DevPathNode;\r
1119 ATAPI_DEVICE_PATH *Atapi;\r
1120\r
1121 //\r
1122 // Examine all new handles\r
1123 //\r
1124 for (;;) {\r
1125 //\r
1126 // Get the next handle\r
1127 //\r
1128 BufferSize = sizeof (Handle);\r
1129 Status = gBS->LocateHandle (\r
1130 ByRegisterNotify,\r
1131 NULL,\r
1132 mEfiDevPathNotifyReg,\r
1133 &BufferSize,\r
1134 &Handle\r
1135 );\r
1136\r
1137 //\r
1138 // If not found, we're done\r
1139 //\r
1140 if (EFI_NOT_FOUND == Status) {\r
1141 break;\r
1142 }\r
1143\r
1144 if (EFI_ERROR (Status)) {\r
1145 continue;\r
1146 }\r
1147\r
1148 //\r
1149 // Get the DevicePath protocol on that handle\r
1150 //\r
1151 Status = gBS->HandleProtocol (Handle, &gEfiDevicePathProtocolGuid, (VOID **)&DevPathNode);\r
1152 ASSERT_EFI_ERROR (Status);\r
1153\r
1154 while (!IsDevicePathEnd (DevPathNode)) {\r
1155 //\r
1156 // Find the handler to dump this device path node\r
1157 //\r
1158 if (\r
1159 (DevicePathType(DevPathNode) == MESSAGING_DEVICE_PATH) &&\r
1160 (DevicePathSubType(DevPathNode) == MSG_ATAPI_DP)\r
1161 ) {\r
1162 Atapi = (ATAPI_DEVICE_PATH*) DevPathNode;\r
1163 PciOr16 (\r
1164 PCI_LIB_ADDRESS (\r
1165 0,\r
1166 1,\r
1167 1,\r
1168 (Atapi->PrimarySecondary == 1) ? 0x42: 0x40\r
1169 ),\r
1170 BIT15\r
1171 );\r
1172 }\r
1173\r
1174 //\r
1175 // Next device path node\r
1176 //\r
1177 DevPathNode = NextDevicePathNode (DevPathNode);\r
1178 }\r
1179 }\r
1180\r
1181 return;\r
1182}\r
1183\r
1184\r
1185VOID\r
1186InstallDevicePathCallback (\r
1187 VOID\r
1188 )\r
1189{\r
1190 DEBUG ((EFI_D_INFO, "Registered NotifyDevPath Event\n"));\r
1191 mEfiDevPathEvent = EfiCreateProtocolNotifyEvent (\r
1192 &gEfiDevicePathProtocolGuid,\r
1193 TPL_CALLBACK,\r
1194 NotifyDevPath,\r
1195 NULL,\r
1196 &mEfiDevPathNotifyReg\r
1197 );\r
1198}\r
1199\r
24cdd14e
LG
1200/**\r
1201 Lock the ConsoleIn device in system table. All key\r
1202 presses will be ignored until the Password is typed in. The only way to\r
1203 disable the password is to type it in to a ConIn device.\r
1204\r
1205 @param Password Password used to lock ConIn device.\r
1206\r
1207 @retval EFI_SUCCESS lock the Console In Spliter virtual handle successfully.\r
1208 @retval EFI_UNSUPPORTED Password not found\r
1209\r
1210**/\r
1211EFI_STATUS\r
1212EFIAPI\r
1213LockKeyboards (\r
1214 IN CHAR16 *Password\r
1215 )\r
1216{\r
1217 return EFI_UNSUPPORTED;\r
1218}\r
5106d422 1219\r
1220\r
1221STATIC\r
1222VOID\r
1223LoadVideoRom (\r
ccd4b7da 1224 VOID\r
5106d422 1225 )\r
1226{\r
1227 PCI_DATA_STRUCTURE *Pcir;\r
1228 UINTN RomSize;\r
1229\r
1230 //\r
1231 // The virtual machines sometimes load the video rom image\r
1232 // directly at the legacy video BIOS location of C000:0000,\r
1233 // and do not implement the PCI expansion ROM feature.\r
1234 //\r
1235 Pcir = (PCI_DATA_STRUCTURE *) (UINTN) 0xc0000;\r
1236 RomSize = Pcir->ImageLength * 512;\r
1237 PciRomLoadEfiDriversFromRomImage (0xc0000, RomSize);\r
1238}\r
1239\r
1240\r
1241STATIC\r
1242EFI_STATUS\r
1243PciRomLoadEfiDriversFromRomImage (\r
1244 IN EFI_PHYSICAL_ADDRESS Rom,\r
1245 IN UINTN RomSize\r
1246 )\r
1247{\r
1248 CHAR16 *FileName;\r
1249 EFI_PCI_EXPANSION_ROM_HEADER *EfiRomHeader;\r
1250 PCI_DATA_STRUCTURE *Pcir;\r
1251 UINTN ImageIndex;\r
1252 UINTN RomOffset;\r
1253 UINT32 ImageSize;\r
1254 UINT16 ImageOffset;\r
1255 EFI_HANDLE ImageHandle;\r
1256 EFI_STATUS Status;\r
1257 EFI_STATUS retStatus;\r
1258 EFI_DEVICE_PATH_PROTOCOL *FilePath;\r
1259 BOOLEAN SkipImage;\r
1260 UINT32 DestinationSize;\r
1261 UINT32 ScratchSize;\r
1262 UINT8 *Scratch;\r
1263 VOID *ImageBuffer;\r
1264 VOID *DecompressedImageBuffer;\r
1265 UINT32 ImageLength;\r
1266 EFI_DECOMPRESS_PROTOCOL *Decompress;\r
1267\r
1268 FileName = L"PciRomInMemory";\r
1269\r
1270 //FileName = L"PciRom Addr=0000000000000000";\r
1271 //HexToString (&FileName[12], Rom, 16);\r
1272\r
1273 ImageIndex = 0;\r
1274 retStatus = EFI_NOT_FOUND;\r
1275 RomOffset = (UINTN) Rom;\r
1276\r
1277 do {\r
1278\r
1279 EfiRomHeader = (EFI_PCI_EXPANSION_ROM_HEADER *) (UINTN) RomOffset;\r
1280\r
1281 if (EfiRomHeader->Signature != 0xaa55) {\r
1282 return retStatus;\r
1283 }\r
1284\r
1285 Pcir = (PCI_DATA_STRUCTURE *) (UINTN) (RomOffset + EfiRomHeader->PcirOffset);\r
1286 ImageSize = Pcir->ImageLength * 512;\r
1287\r
1288 if ((Pcir->CodeType == PCI_CODE_TYPE_EFI_IMAGE) &&\r
1289 (EfiRomHeader->EfiSignature == EFI_PCI_EXPANSION_ROM_HEADER_EFISIGNATURE) ) {\r
1290\r
1291 if ((EfiRomHeader->EfiSubsystem == EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER) ||\r
1292 (EfiRomHeader->EfiSubsystem == EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER) ) {\r
1293\r
1294 ImageOffset = EfiRomHeader->EfiImageHeaderOffset;\r
1295 ImageSize = EfiRomHeader->InitializationSize * 512;\r
1296\r
1297 ImageBuffer = (VOID *) (UINTN) (RomOffset + ImageOffset);\r
1298 ImageLength = ImageSize - ImageOffset;\r
1299 DecompressedImageBuffer = NULL;\r
1300\r
1301 //\r
1302 // decompress here if needed\r
1303 //\r
1304 SkipImage = FALSE;\r
1305 if (EfiRomHeader->CompressionType > EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED) {\r
1306 SkipImage = TRUE;\r
1307 }\r
1308\r
1309 if (EfiRomHeader->CompressionType == EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED) {\r
1310 Status = gBS->LocateProtocol (&gEfiDecompressProtocolGuid, NULL, (VOID **) &Decompress);\r
1311 if (EFI_ERROR (Status)) {\r
1312 SkipImage = TRUE;\r
1313 } else {\r
1314 SkipImage = TRUE;\r
1315 Status = Decompress->GetInfo (\r
1316 Decompress,\r
1317 ImageBuffer,\r
1318 ImageLength,\r
1319 &DestinationSize,\r
1320 &ScratchSize\r
1321 );\r
1322 if (!EFI_ERROR (Status)) {\r
1323 DecompressedImageBuffer = NULL;\r
1324 DecompressedImageBuffer = AllocatePool (DestinationSize);\r
1325 if (DecompressedImageBuffer != NULL) {\r
1326 Scratch = AllocatePool (ScratchSize);\r
1327 if (Scratch != NULL) {\r
1328 Status = Decompress->Decompress (\r
1329 Decompress,\r
1330 ImageBuffer,\r
1331 ImageLength,\r
1332 DecompressedImageBuffer,\r
1333 DestinationSize,\r
1334 Scratch,\r
1335 ScratchSize\r
1336 );\r
1337 if (!EFI_ERROR (Status)) {\r
1338 ImageBuffer = DecompressedImageBuffer;\r
1339 ImageLength = DestinationSize;\r
1340 SkipImage = FALSE;\r
1341 }\r
1342\r
1343 gBS->FreePool (Scratch);\r
1344 }\r
1345 }\r
1346 }\r
1347 }\r
1348 }\r
1349\r
1350 if (!SkipImage) {\r
1351\r
1352 //\r
1353 // load image and start image\r
1354 //\r
1355\r
1356 FilePath = FileDevicePath (NULL, FileName);\r
1357\r
1358 Status = gBS->LoadImage (\r
1359 FALSE,\r
1360 gImageHandle,\r
1361 FilePath,\r
1362 ImageBuffer,\r
1363 ImageLength,\r
1364 &ImageHandle\r
1365 );\r
1366 if (!EFI_ERROR (Status)) {\r
1367 Status = gBS->StartImage (ImageHandle, NULL, NULL);\r
1368 if (!EFI_ERROR (Status)) {\r
1369 retStatus = Status;\r
1370 }\r
1371 }\r
1372 if (FilePath != NULL) {\r
1373 gBS->FreePool (FilePath);\r
1374 }\r
1375 }\r
1376\r
1377 if (DecompressedImageBuffer != NULL) {\r
1378 gBS->FreePool (DecompressedImageBuffer);\r
1379 }\r
1380\r
1381 }\r
1382 }\r
1383\r
1384 RomOffset = RomOffset + ImageSize;\r
1385 ImageIndex++;\r
1386 } while (((Pcir->Indicator & 0x80) == 0x00) && ((RomOffset - (UINTN) Rom) < RomSize));\r
1387\r
1388 return retStatus;\r
1389}\r
1390\r
1391\r