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