]> git.proxmox.com Git - mirror_edk2.git/blame - OvmfPkg/Library/PlatformBdsLib/BdsPlatform.c
OvmfPkg: PlatformBdsLib: signal gRootBridgesConnectedEventGroupGuid
[mirror_edk2.git] / OvmfPkg / Library / PlatformBdsLib / BdsPlatform.c
CommitLineData
49ba9447 1/** @file\r
2 Platform BDS customizations.\r
3\r
ea5396f3 4 Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.<BR>\r
56d7640a 5 This program and the accompanying materials\r
49ba9447 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
0f6ff51d 16#include <Guid/RootBridgesConnectedEventGroup.h>\r
cca7475b 17#include <Library/QemuBootOrderLib.h>\r
49ba9447 18\r
19\r
40f2c454 20//\r
21// Global data\r
22//\r
23\r
24VOID *mEfiDevPathNotifyReg;\r
25EFI_EVENT mEfiDevPathEvent;\r
9607962d 26VOID *mEmuVariableEventReg;\r
27EFI_EVENT mEmuVariableEvent;\r
e955462b 28BOOLEAN mDetectVgaOnly;\r
5218c279 29UINT16 mHostBridgeDevId;\r
e955462b 30\r
5218c279
GS
31//\r
32// Table of host IRQs matching PCI IRQs A-D\r
33// (for configuring PCI Interrupt Line register)\r
34//\r
35CONST UINT8 PciHostIrqs[] = {\r
36 0x0a, 0x0a, 0x0b, 0x0b\r
37};\r
38\r
39//\r
40// Array Size macro\r
41//\r
42#define ARRAY_SIZE(array) (sizeof (array) / sizeof (array[0]))\r
e955462b 43\r
44//\r
45// Type definitions\r
46//\r
47\r
48typedef\r
49EFI_STATUS\r
50(EFIAPI *PROTOCOL_INSTANCE_CALLBACK)(\r
51 IN EFI_HANDLE Handle,\r
52 IN VOID *Instance,\r
53 IN VOID *Context\r
54 );\r
55\r
56/**\r
57 @param[in] Handle - Handle of PCI device instance\r
58 @param[in] PciIo - PCI IO protocol instance\r
59 @param[in] Pci - PCI Header register block\r
60**/\r
61typedef\r
62EFI_STATUS\r
63(EFIAPI *VISIT_PCI_INSTANCE_CALLBACK)(\r
64 IN EFI_HANDLE Handle,\r
65 IN EFI_PCI_IO_PROTOCOL *PciIo,\r
66 IN PCI_TYPE00 *Pci\r
67 );\r
40f2c454 68\r
69\r
70//\r
71// Function prototypes\r
72//\r
73\r
e955462b 74EFI_STATUS\r
75VisitAllInstancesOfProtocol (\r
76 IN EFI_GUID *Id,\r
77 IN PROTOCOL_INSTANCE_CALLBACK CallBackFunction,\r
78 IN VOID *Context\r
79 );\r
80\r
81EFI_STATUS\r
82VisitAllPciInstancesOfProtocol (\r
83 IN VISIT_PCI_INSTANCE_CALLBACK CallBackFunction\r
84 );\r
85\r
40f2c454 86VOID\r
87InstallDevicePathCallback (\r
88 VOID\r
89 );\r
90\r
49ba9447 91//\r
92// BDS Platform Functions\r
93//\r
94VOID\r
95EFIAPI\r
96PlatformBdsInit (\r
370ec7f1 97 VOID\r
49ba9447 98 )\r
99/*++\r
100\r
101Routine Description:\r
102\r
103 Platform Bds init. Incude the platform firmware vendor, revision\r
104 and so crc check.\r
105\r
106Arguments:\r
107\r
49ba9447 108Returns:\r
109\r
110 None.\r
111\r
112--*/\r
113{\r
114 DEBUG ((EFI_D_INFO, "PlatformBdsInit\n"));\r
40f2c454 115 InstallDevicePathCallback ();\r
49ba9447 116}\r
117\r
118\r
119EFI_STATUS\r
2c34f3bc 120EFIAPI\r
49ba9447 121ConnectRootBridge (\r
2c34f3bc
LE
122 IN EFI_HANDLE RootBridgeHandle,\r
123 IN VOID *Instance,\r
124 IN VOID *Context\r
49ba9447 125 )\r
49ba9447 126{\r
2c34f3bc 127 EFI_STATUS Status;\r
49ba9447 128\r
129 //\r
2c34f3bc
LE
130 // Make the PCI bus driver connect the root bridge, non-recursively. This\r
131 // will produce a number of child handles with PciIo on them.\r
49ba9447 132 //\r
2c34f3bc
LE
133 Status = gBS->ConnectController (\r
134 RootBridgeHandle, // ControllerHandle\r
135 NULL, // DriverImageHandle\r
136 NULL, // RemainingDevicePath -- produce all\r
137 // children\r
138 FALSE // Recursive\r
49ba9447 139 );\r
2c34f3bc 140 return Status;\r
49ba9447 141}\r
142\r
143\r
144EFI_STATUS\r
145PrepareLpcBridgeDevicePath (\r
146 IN EFI_HANDLE DeviceHandle\r
147 )\r
148/*++\r
149\r
150Routine Description:\r
151\r
152 Add IsaKeyboard to ConIn,\r
153 add IsaSerial to ConOut, ConIn, ErrOut.\r
154 LPC Bridge: 06 01 00\r
155\r
156Arguments:\r
157\r
158 DeviceHandle - Handle of PCIIO protocol.\r
159\r
160Returns:\r
161\r
162 EFI_SUCCESS - LPC bridge is added to ConOut, ConIn, and ErrOut.\r
163 EFI_STATUS - No LPC bridge is added.\r
164\r
165--*/\r
166{\r
167 EFI_STATUS Status;\r
168 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
169 EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;\r
170 CHAR16 *DevPathStr;\r
171\r
172 DevicePath = NULL;\r
173 Status = gBS->HandleProtocol (\r
174 DeviceHandle,\r
175 &gEfiDevicePathProtocolGuid,\r
176 (VOID*)&DevicePath\r
177 );\r
178 if (EFI_ERROR (Status)) {\r
179 return Status;\r
180 }\r
181 TempDevicePath = DevicePath;\r
182\r
183 //\r
184 // Register Keyboard\r
185 //\r
186 DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gPnpPs2KeyboardDeviceNode);\r
187\r
188 BdsLibUpdateConsoleVariable (VarConsoleInp, DevicePath, NULL);\r
189\r
190 //\r
191 // Register COM1\r
192 //\r
193 DevicePath = TempDevicePath;\r
194 gPnp16550ComPortDeviceNode.UID = 0;\r
195\r
196 DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gPnp16550ComPortDeviceNode);\r
197 DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gUartDeviceNode);\r
198 DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gTerminalTypeDeviceNode);\r
199\r
200 //\r
201 // Print Device Path\r
202 //\r
203 DevPathStr = DevicePathToStr(DevicePath);\r
863986b3
RN
204 if (DevPathStr != NULL) {\r
205 DEBUG((\r
206 EFI_D_INFO,\r
207 "BdsPlatform.c+%d: COM%d DevPath: %s\n",\r
208 __LINE__,\r
209 gPnp16550ComPortDeviceNode.UID + 1,\r
210 DevPathStr\r
211 ));\r
212 FreePool(DevPathStr);\r
213 }\r
49ba9447 214\r
215 BdsLibUpdateConsoleVariable (VarConsoleOut, DevicePath, NULL);\r
216 BdsLibUpdateConsoleVariable (VarConsoleInp, DevicePath, NULL);\r
217 BdsLibUpdateConsoleVariable (VarErrorOut, DevicePath, NULL);\r
218\r
219 //\r
220 // Register COM2\r
221 //\r
222 DevicePath = TempDevicePath;\r
223 gPnp16550ComPortDeviceNode.UID = 1;\r
224\r
225 DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gPnp16550ComPortDeviceNode);\r
226 DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gUartDeviceNode);\r
227 DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gTerminalTypeDeviceNode);\r
228\r
229 //\r
230 // Print Device Path\r
231 //\r
232 DevPathStr = DevicePathToStr(DevicePath);\r
863986b3
RN
233 if (DevPathStr != NULL) {\r
234 DEBUG((\r
235 EFI_D_INFO,\r
236 "BdsPlatform.c+%d: COM%d DevPath: %s\n",\r
237 __LINE__,\r
238 gPnp16550ComPortDeviceNode.UID + 1,\r
239 DevPathStr\r
240 ));\r
241 FreePool(DevPathStr);\r
242 }\r
49ba9447 243\r
244 BdsLibUpdateConsoleVariable (VarConsoleOut, DevicePath, NULL);\r
245 BdsLibUpdateConsoleVariable (VarConsoleInp, DevicePath, NULL);\r
246 BdsLibUpdateConsoleVariable (VarErrorOut, DevicePath, NULL);\r
247\r
248 return EFI_SUCCESS;\r
249}\r
250\r
251EFI_STATUS\r
252GetGopDevicePath (\r
253 IN EFI_DEVICE_PATH_PROTOCOL *PciDevicePath,\r
254 OUT EFI_DEVICE_PATH_PROTOCOL **GopDevicePath\r
255 )\r
256{\r
257 UINTN Index;\r
258 EFI_STATUS Status;\r
259 EFI_HANDLE PciDeviceHandle;\r
260 EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;\r
261 EFI_DEVICE_PATH_PROTOCOL *TempPciDevicePath;\r
262 UINTN GopHandleCount;\r
263 EFI_HANDLE *GopHandleBuffer;\r
264\r
265 if (PciDevicePath == NULL || GopDevicePath == NULL) {\r
266 return EFI_INVALID_PARAMETER;\r
267 }\r
268\r
269 //\r
270 // Initialize the GopDevicePath to be PciDevicePath\r
271 //\r
272 *GopDevicePath = PciDevicePath;\r
273 TempPciDevicePath = PciDevicePath;\r
274\r
275 Status = gBS->LocateDevicePath (\r
276 &gEfiDevicePathProtocolGuid,\r
277 &TempPciDevicePath,\r
278 &PciDeviceHandle\r
279 );\r
280 if (EFI_ERROR (Status)) {\r
281 return Status;\r
282 }\r
283\r
284 //\r
285 // Try to connect this handle, so that GOP dirver could start on this\r
286 // device and create child handles with GraphicsOutput Protocol installed\r
287 // on them, then we get device paths of these child handles and select\r
288 // them as possible console device.\r
289 //\r
290 gBS->ConnectController (PciDeviceHandle, NULL, NULL, FALSE);\r
291\r
292 Status = gBS->LocateHandleBuffer (\r
293 ByProtocol,\r
294 &gEfiGraphicsOutputProtocolGuid,\r
295 NULL,\r
296 &GopHandleCount,\r
297 &GopHandleBuffer\r
298 );\r
299 if (!EFI_ERROR (Status)) {\r
300 //\r
301 // Add all the child handles as possible Console Device\r
302 //\r
303 for (Index = 0; Index < GopHandleCount; Index++) {\r
304 Status = gBS->HandleProtocol (GopHandleBuffer[Index], &gEfiDevicePathProtocolGuid, (VOID*)&TempDevicePath);\r
305 if (EFI_ERROR (Status)) {\r
306 continue;\r
307 }\r
308 if (CompareMem (\r
309 PciDevicePath,\r
310 TempDevicePath,\r
311 GetDevicePathSize (PciDevicePath) - END_DEVICE_PATH_LENGTH\r
312 ) == 0) {\r
313 //\r
314 // In current implementation, we only enable one of the child handles\r
315 // as console device, i.e. sotre one of the child handle's device\r
316 // path to variable "ConOut"\r
317 // In futhure, we could select all child handles to be console device\r
318 //\r
319\r
320 *GopDevicePath = TempDevicePath;\r
321\r
322 //\r
323 // Delete the PCI device's path that added by GetPlugInPciVgaDevicePath()\r
324 // Add the integrity GOP device path.\r
325 //\r
326 BdsLibUpdateConsoleVariable (VarConsoleOutDev, NULL, PciDevicePath);\r
327 BdsLibUpdateConsoleVariable (VarConsoleOutDev, TempDevicePath, NULL);\r
328 }\r
329 }\r
330 gBS->FreePool (GopHandleBuffer);\r
331 }\r
332\r
333 return EFI_SUCCESS;\r
334}\r
335\r
336EFI_STATUS\r
337PreparePciVgaDevicePath (\r
338 IN EFI_HANDLE DeviceHandle\r
339 )\r
340/*++\r
341\r
342Routine Description:\r
343\r
344 Add PCI VGA to ConOut.\r
345 PCI VGA: 03 00 00\r
346\r
347Arguments:\r
348\r
349 DeviceHandle - Handle of PCIIO protocol.\r
350\r
351Returns:\r
352\r
353 EFI_SUCCESS - PCI VGA is added to ConOut.\r
354 EFI_STATUS - No PCI VGA device is added.\r
355\r
356--*/\r
357{\r
358 EFI_STATUS Status;\r
359 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
360 EFI_DEVICE_PATH_PROTOCOL *GopDevicePath;\r
361\r
ea5396f3
RN
362 DevicePath = NULL;\r
363 GopDevicePath = NULL;\r
49ba9447 364 Status = gBS->HandleProtocol (\r
365 DeviceHandle,\r
366 &gEfiDevicePathProtocolGuid,\r
367 (VOID*)&DevicePath\r
368 );\r
369 if (EFI_ERROR (Status)) {\r
370 return Status;\r
371 }\r
372\r
373 GetGopDevicePath (DevicePath, &GopDevicePath);\r
374 DevicePath = GopDevicePath;\r
375\r
376 BdsLibUpdateConsoleVariable (VarConsoleOut, DevicePath, NULL);\r
377\r
378 return EFI_SUCCESS;\r
379}\r
380\r
381EFI_STATUS\r
382PreparePciSerialDevicePath (\r
383 IN EFI_HANDLE DeviceHandle\r
384 )\r
385/*++\r
386\r
387Routine Description:\r
388\r
389 Add PCI Serial to ConOut, ConIn, ErrOut.\r
390 PCI Serial: 07 00 02\r
391\r
392Arguments:\r
393\r
394 DeviceHandle - Handle of PCIIO protocol.\r
395\r
396Returns:\r
397\r
398 EFI_SUCCESS - PCI Serial is added to ConOut, ConIn, and ErrOut.\r
399 EFI_STATUS - No PCI Serial device is added.\r
400\r
401--*/\r
402{\r
403 EFI_STATUS Status;\r
404 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
405\r
406 DevicePath = NULL;\r
407 Status = gBS->HandleProtocol (\r
408 DeviceHandle,\r
409 &gEfiDevicePathProtocolGuid,\r
410 (VOID*)&DevicePath\r
411 );\r
412 if (EFI_ERROR (Status)) {\r
413 return Status;\r
414 }\r
415\r
416 DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gUartDeviceNode);\r
417 DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gTerminalTypeDeviceNode);\r
418\r
419 BdsLibUpdateConsoleVariable (VarConsoleOut, DevicePath, NULL);\r
420 BdsLibUpdateConsoleVariable (VarConsoleInp, DevicePath, NULL);\r
421 BdsLibUpdateConsoleVariable (VarErrorOut, DevicePath, NULL);\r
422\r
423 return EFI_SUCCESS;\r
424}\r
425\r
426EFI_STATUS\r
e955462b 427VisitAllInstancesOfProtocol (\r
428 IN EFI_GUID *Id,\r
429 IN PROTOCOL_INSTANCE_CALLBACK CallBackFunction,\r
430 IN VOID *Context\r
49ba9447 431 )\r
49ba9447 432{\r
433 EFI_STATUS Status;\r
434 UINTN HandleCount;\r
435 EFI_HANDLE *HandleBuffer;\r
436 UINTN Index;\r
e955462b 437 VOID *Instance;\r
49ba9447 438\r
439 //\r
440 // Start to check all the PciIo to find all possible device\r
441 //\r
442 HandleCount = 0;\r
443 HandleBuffer = NULL;\r
444 Status = gBS->LocateHandleBuffer (\r
445 ByProtocol,\r
e955462b 446 Id,\r
49ba9447 447 NULL,\r
448 &HandleCount,\r
449 &HandleBuffer\r
450 );\r
451 if (EFI_ERROR (Status)) {\r
452 return Status;\r
453 }\r
454\r
455 for (Index = 0; Index < HandleCount; Index++) {\r
e955462b 456 Status = gBS->HandleProtocol (HandleBuffer[Index], Id, &Instance);\r
49ba9447 457 if (EFI_ERROR (Status)) {\r
458 continue;\r
459 }\r
460\r
e955462b 461 Status = (*CallBackFunction) (\r
462 HandleBuffer[Index],\r
463 Instance,\r
464 Context\r
465 );\r
466 }\r
49ba9447 467\r
e955462b 468 gBS->FreePool (HandleBuffer);\r
607ca510 469\r
e955462b 470 return EFI_SUCCESS;\r
471}\r
472\r
473\r
474EFI_STATUS\r
475EFIAPI\r
476VisitingAPciInstance (\r
477 IN EFI_HANDLE Handle,\r
478 IN VOID *Instance,\r
479 IN VOID *Context\r
480 )\r
481{\r
482 EFI_STATUS Status;\r
483 EFI_PCI_IO_PROTOCOL *PciIo;\r
484 PCI_TYPE00 Pci;\r
485\r
486 PciIo = (EFI_PCI_IO_PROTOCOL*) Instance;\r
487\r
488 //\r
489 // Check for all PCI device\r
490 //\r
491 Status = PciIo->Pci.Read (\r
492 PciIo,\r
493 EfiPciIoWidthUint32,\r
494 0,\r
495 sizeof (Pci) / sizeof (UINT32),\r
496 &Pci\r
497 );\r
498 if (EFI_ERROR (Status)) {\r
499 return Status;\r
500 }\r
501\r
7d9cf3f2 502 return (*(VISIT_PCI_INSTANCE_CALLBACK)(UINTN) Context) (\r
e955462b 503 Handle,\r
504 PciIo,\r
505 &Pci\r
506 );\r
507\r
508}\r
509\r
510\r
511\r
512EFI_STATUS\r
513VisitAllPciInstances (\r
514 IN VISIT_PCI_INSTANCE_CALLBACK CallBackFunction\r
515 )\r
516{\r
517 return VisitAllInstancesOfProtocol (\r
518 &gEfiPciIoProtocolGuid,\r
519 VisitingAPciInstance,\r
7d9cf3f2 520 (VOID*)(UINTN) CallBackFunction\r
e955462b 521 );\r
522}\r
523\r
524\r
525/**\r
526 Do platform specific PCI Device check and add them to\r
527 ConOut, ConIn, ErrOut.\r
528\r
529 @param[in] Handle - Handle of PCI device instance\r
530 @param[in] PciIo - PCI IO protocol instance\r
531 @param[in] Pci - PCI Header register block\r
532\r
533 @retval EFI_SUCCESS - PCI Device check and Console variable update successfully.\r
534 @retval EFI_STATUS - PCI Device check or Console variable update fail.\r
535\r
536**/\r
537EFI_STATUS\r
8861fc79 538EFIAPI\r
e955462b 539DetectAndPreparePlatformPciDevicePath (\r
540 IN EFI_HANDLE Handle,\r
541 IN EFI_PCI_IO_PROTOCOL *PciIo,\r
542 IN PCI_TYPE00 *Pci\r
543 )\r
544{\r
545 EFI_STATUS Status;\r
546\r
547 Status = PciIo->Attributes (\r
548 PciIo,\r
549 EfiPciIoAttributeOperationEnable,\r
550 EFI_PCI_DEVICE_ENABLE,\r
551 NULL\r
552 );\r
553 ASSERT_EFI_ERROR (Status);\r
554\r
555 if (!mDetectVgaOnly) {\r
556 //\r
557 // Here we decide whether it is LPC Bridge\r
558 //\r
559 if ((IS_PCI_LPC (Pci)) ||\r
560 ((IS_PCI_ISA_PDECODE (Pci)) &&\r
561 (Pci->Hdr.VendorId == 0x8086) &&\r
562 (Pci->Hdr.DeviceId == 0x7000)\r
563 )\r
564 ) {\r
49ba9447 565 //\r
e955462b 566 // Add IsaKeyboard to ConIn,\r
567 // add IsaSerial to ConOut, ConIn, ErrOut\r
49ba9447 568 //\r
e955462b 569 DEBUG ((EFI_D_INFO, "Found LPC Bridge device\n"));\r
570 PrepareLpcBridgeDevicePath (Handle);\r
571 return EFI_SUCCESS;\r
49ba9447 572 }\r
49ba9447 573 //\r
e955462b 574 // Here we decide which Serial device to enable in PCI bus\r
49ba9447 575 //\r
e955462b 576 if (IS_PCI_16550SERIAL (Pci)) {\r
49ba9447 577 //\r
e955462b 578 // Add them to ConOut, ConIn, ErrOut.\r
49ba9447 579 //\r
e955462b 580 DEBUG ((EFI_D_INFO, "Found PCI 16550 SERIAL device\n"));\r
581 PreparePciSerialDevicePath (Handle);\r
582 return EFI_SUCCESS;\r
49ba9447 583 }\r
584 }\r
585\r
e955462b 586 //\r
587 // Here we decide which VGA device to enable in PCI bus\r
588 //\r
589 if (IS_PCI_VGA (Pci)) {\r
590 //\r
591 // Add them to ConOut.\r
592 //\r
593 DEBUG ((EFI_D_INFO, "Found PCI VGA device\n"));\r
594 PreparePciVgaDevicePath (Handle);\r
595 return EFI_SUCCESS;\r
596 }\r
49ba9447 597\r
e955462b 598 return Status;\r
599}\r
600\r
601\r
602/**\r
603 Do platform specific PCI Device check and add them to ConOut, ConIn, ErrOut\r
604\r
605 @param[in] DetectVgaOnly - Only detect VGA device if it's TRUE.\r
606\r
607 @retval EFI_SUCCESS - PCI Device check and Console variable update successfully.\r
608 @retval EFI_STATUS - PCI Device check or Console variable update fail.\r
609\r
610**/\r
611EFI_STATUS\r
612DetectAndPreparePlatformPciDevicePaths (\r
613 BOOLEAN DetectVgaOnly\r
614 )\r
615{\r
616 mDetectVgaOnly = DetectVgaOnly;\r
617 return VisitAllPciInstances (DetectAndPreparePlatformPciDevicePath);\r
49ba9447 618}\r
619\r
620\r
621EFI_STATUS\r
622PlatformBdsConnectConsole (\r
623 IN BDS_CONSOLE_CONNECT_ENTRY *PlatformConsole\r
624 )\r
625/*++\r
626\r
627Routine Description:\r
628\r
629 Connect the predefined platform default console device. Always try to find\r
630 and enable the vga device if have.\r
631\r
632Arguments:\r
633\r
634 PlatformConsole - Predfined platform default console device array.\r
635\r
636Returns:\r
637\r
638 EFI_SUCCESS - Success connect at least one ConIn and ConOut\r
639 device, there must have one ConOut device is\r
640 active vga device.\r
641\r
642 EFI_STATUS - Return the status of\r
643 BdsLibConnectAllDefaultConsoles ()\r
644\r
645--*/\r
646{\r
647 EFI_STATUS Status;\r
648 UINTN Index;\r
649 EFI_DEVICE_PATH_PROTOCOL *VarConout;\r
650 EFI_DEVICE_PATH_PROTOCOL *VarConin;\r
651 UINTN DevicePathSize;\r
652\r
653 //\r
654 // Connect RootBridge\r
655 //\r
49ba9447 656 VarConout = BdsLibGetVariableAndSize (\r
657 VarConsoleOut,\r
658 &gEfiGlobalVariableGuid,\r
659 &DevicePathSize\r
660 );\r
661 VarConin = BdsLibGetVariableAndSize (\r
662 VarConsoleInp,\r
663 &gEfiGlobalVariableGuid,\r
664 &DevicePathSize\r
665 );\r
666\r
667 if (VarConout == NULL || VarConin == NULL) {\r
668 //\r
669 // Do platform specific PCI Device check and add them to ConOut, ConIn, ErrOut\r
670 //\r
e955462b 671 DetectAndPreparePlatformPciDevicePaths (FALSE);\r
49ba9447 672\r
673 //\r
674 // Have chance to connect the platform default console,\r
675 // the platform default console is the minimue device group\r
676 // the platform should support\r
677 //\r
678 for (Index = 0; PlatformConsole[Index].DevicePath != NULL; ++Index) {\r
679 //\r
680 // Update the console variable with the connect type\r
681 //\r
682 if ((PlatformConsole[Index].ConnectType & CONSOLE_IN) == CONSOLE_IN) {\r
683 BdsLibUpdateConsoleVariable (VarConsoleInp, PlatformConsole[Index].DevicePath, NULL);\r
684 }\r
685 if ((PlatformConsole[Index].ConnectType & CONSOLE_OUT) == CONSOLE_OUT) {\r
686 BdsLibUpdateConsoleVariable (VarConsoleOut, PlatformConsole[Index].DevicePath, NULL);\r
687 }\r
688 if ((PlatformConsole[Index].ConnectType & STD_ERROR) == STD_ERROR) {\r
689 BdsLibUpdateConsoleVariable (VarErrorOut, PlatformConsole[Index].DevicePath, NULL);\r
690 }\r
691 }\r
692 } else {\r
693 //\r
694 // Only detect VGA device and add them to ConOut\r
695 //\r
e955462b 696 DetectAndPreparePlatformPciDevicePaths (TRUE);\r
49ba9447 697 }\r
698\r
699 //\r
700 // Connect the all the default console with current cosole variable\r
701 //\r
702 Status = BdsLibConnectAllDefaultConsoles ();\r
703 if (EFI_ERROR (Status)) {\r
704 return Status;\r
705 }\r
706\r
707 return EFI_SUCCESS;\r
708}\r
709\r
710\r
5218c279
GS
711/**\r
712 Configure PCI Interrupt Line register for applicable devices\r
713 Ported from SeaBIOS, src/fw/pciinit.c, *_pci_slot_get_irq()\r
714\r
715 @param[in] Handle - Handle of PCI device instance\r
716 @param[in] PciIo - PCI IO protocol instance\r
717 @param[in] PciHdr - PCI Header register block\r
718\r
719 @retval EFI_SUCCESS - PCI Interrupt Line register configured successfully.\r
720\r
721**/\r
722EFI_STATUS\r
723EFIAPI\r
724SetPciIntLine (\r
725 IN EFI_HANDLE Handle,\r
726 IN EFI_PCI_IO_PROTOCOL *PciIo,\r
727 IN PCI_TYPE00 *PciHdr\r
728 )\r
729{\r
730 EFI_DEVICE_PATH_PROTOCOL *DevPathNode;\r
fcd1e5de 731 EFI_DEVICE_PATH_PROTOCOL *DevPath;\r
5218c279
GS
732 UINTN RootSlot;\r
733 UINTN Idx;\r
734 UINT8 IrqLine;\r
735 EFI_STATUS Status;\r
7730ad6e 736 UINT32 RootBusNumber;\r
5218c279
GS
737\r
738 Status = EFI_SUCCESS;\r
739\r
740 if (PciHdr->Device.InterruptPin != 0) {\r
741\r
742 DevPathNode = DevicePathFromHandle (Handle);\r
743 ASSERT (DevPathNode != NULL);\r
fcd1e5de 744 DevPath = DevPathNode;\r
5218c279 745\r
7730ad6e
LE
746 RootBusNumber = 0;\r
747 if (DevicePathType (DevPathNode) == ACPI_DEVICE_PATH &&\r
748 DevicePathSubType (DevPathNode) == ACPI_DP &&\r
749 ((ACPI_HID_DEVICE_PATH *)DevPathNode)->HID == EISA_PNP_ID(0x0A03)) {\r
750 RootBusNumber = ((ACPI_HID_DEVICE_PATH *)DevPathNode)->UID;\r
751 }\r
752\r
5218c279
GS
753 //\r
754 // Compute index into PciHostIrqs[] table by walking\r
755 // the device path and adding up all device numbers\r
756 //\r
757 Status = EFI_NOT_FOUND;\r
758 RootSlot = 0;\r
759 Idx = PciHdr->Device.InterruptPin - 1;\r
760 while (!IsDevicePathEnd (DevPathNode)) {\r
761 if (DevicePathType (DevPathNode) == HARDWARE_DEVICE_PATH &&\r
762 DevicePathSubType (DevPathNode) == HW_PCI_DP) {\r
763\r
764 Idx += ((PCI_DEVICE_PATH *)DevPathNode)->Device;\r
765\r
766 //\r
767 // Unlike SeaBIOS, which starts climbing from the leaf device\r
768 // up toward the root, we traverse the device path starting at\r
769 // the root moving toward the leaf node.\r
770 // The slot number of the top-level parent bridge is needed for\r
771 // Q35 cases with more than 24 slots on the root bus.\r
772 //\r
773 if (Status != EFI_SUCCESS) {\r
774 Status = EFI_SUCCESS;\r
775 RootSlot = ((PCI_DEVICE_PATH *)DevPathNode)->Device;\r
776 }\r
777 }\r
778\r
779 DevPathNode = NextDevicePathNode (DevPathNode);\r
780 }\r
781 if (EFI_ERROR (Status)) {\r
782 return Status;\r
783 }\r
7730ad6e 784 if (RootBusNumber == 0 && RootSlot == 0) {\r
5218c279
GS
785 DEBUG((\r
786 EFI_D_ERROR,\r
787 "%a: PCI host bridge (00:00.0) should have no interrupts!\n",\r
788 __FUNCTION__\r
789 ));\r
790 ASSERT (FALSE);\r
791 }\r
792\r
793 //\r
794 // Final PciHostIrqs[] index calculation depends on the platform\r
795 // and should match SeaBIOS src/fw/pciinit.c *_pci_slot_get_irq()\r
796 //\r
797 switch (mHostBridgeDevId) {\r
798 case INTEL_82441_DEVICE_ID:\r
799 Idx -= 1;\r
800 break;\r
801 case INTEL_Q35_MCH_DEVICE_ID:\r
802 //\r
803 // SeaBIOS contains the following comment:\r
804 // "Slots 0-24 rotate slot:pin mapping similar to piix above, but\r
805 // with a different starting index - see q35-acpi-dsdt.dsl.\r
806 //\r
807 // Slots 25-31 all use LNKA mapping (or LNKE, but A:D = E:H)"\r
808 //\r
809 if (RootSlot > 24) {\r
810 //\r
811 // in this case, subtract back out RootSlot from Idx\r
812 // (SeaBIOS never adds it to begin with, but that would make our\r
813 // device path traversal loop above too awkward)\r
814 //\r
815 Idx -= RootSlot;\r
816 }\r
817 break;\r
818 default:\r
819 ASSERT (FALSE); // should never get here\r
820 }\r
821 Idx %= ARRAY_SIZE (PciHostIrqs);\r
822 IrqLine = PciHostIrqs[Idx];\r
823\r
fcd1e5de
LE
824 DEBUG_CODE_BEGIN ();\r
825 {\r
826 CHAR16 *DevPathString;\r
827 STATIC CHAR16 Fallback[] = L"<failed to convert>";\r
828 UINTN Segment, Bus, Device, Function;\r
829\r
830 DevPathString = ConvertDevicePathToText (DevPath, FALSE, FALSE);\r
831 if (DevPathString == NULL) {\r
832 DevPathString = Fallback;\r
833 }\r
834 Status = PciIo->GetLocation (PciIo, &Segment, &Bus, &Device, &Function);\r
835 ASSERT_EFI_ERROR (Status);\r
836\r
837 DEBUG ((EFI_D_VERBOSE, "%a: [%02x:%02x.%x] %s -> 0x%02x\n", __FUNCTION__,\r
838 (UINT32)Bus, (UINT32)Device, (UINT32)Function, DevPathString,\r
839 IrqLine));\r
840\r
841 if (DevPathString != Fallback) {\r
842 FreePool (DevPathString);\r
843 }\r
844 }\r
845 DEBUG_CODE_END ();\r
846\r
5218c279
GS
847 //\r
848 // Set PCI Interrupt Line register for this device to PciHostIrqs[Idx]\r
849 //\r
850 Status = PciIo->Pci.Write (\r
851 PciIo,\r
852 EfiPciIoWidthUint8,\r
853 PCI_INT_LINE_OFFSET,\r
854 1,\r
855 &IrqLine\r
856 );\r
857 }\r
858\r
859 return Status;\r
860}\r
861\r
862\r
49ba9447 863VOID\r
2e70cf8a 864PciAcpiInitialization (\r
49ba9447 865 )\r
866{\r
2e70cf8a 867 UINTN Pmba;\r
49ba9447 868\r
869 //\r
2e70cf8a 870 // Query Host Bridge DID to determine platform type\r
49ba9447 871 //\r
5218c279
GS
872 mHostBridgeDevId = PcdGet16 (PcdOvmfHostBridgePciDevId);\r
873 switch (mHostBridgeDevId) {\r
2e70cf8a 874 case INTEL_82441_DEVICE_ID:\r
da372167 875 Pmba = POWER_MGMT_REGISTER_PIIX4 (PIIX4_PMBA);\r
2e70cf8a
GS
876 //\r
877 // 00:01.0 ISA Bridge (PIIX4) LNK routing targets\r
878 //\r
879 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x60), 0x0b); // A\r
880 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x61), 0x0b); // B\r
881 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x62), 0x0a); // C\r
882 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x63), 0x0a); // D\r
883 break;\r
884 case INTEL_Q35_MCH_DEVICE_ID:\r
bc9d05d6 885 Pmba = POWER_MGMT_REGISTER_Q35 (ICH9_PMBASE);\r
2e70cf8a
GS
886 //\r
887 // 00:1f.0 LPC Bridge (Q35) LNK routing targets\r
888 //\r
889 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x60), 0x0a); // A\r
890 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x61), 0x0a); // B\r
891 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x62), 0x0b); // C\r
892 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x63), 0x0b); // D\r
893 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x68), 0x0a); // E\r
894 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x69), 0x0a); // F\r
895 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x6a), 0x0b); // G\r
896 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x6b), 0x0b); // H\r
897 break;\r
898 default:\r
899 DEBUG ((EFI_D_ERROR, "%a: Unknown Host Bridge Device ID: 0x%04x\n",\r
5218c279 900 __FUNCTION__, mHostBridgeDevId));\r
2e70cf8a
GS
901 ASSERT (FALSE);\r
902 return;\r
903 }\r
49ba9447 904\r
9b167857 905 //\r
5218c279 906 // Initialize PCI_INTERRUPT_LINE for applicable present PCI devices\r
9b167857 907 //\r
5218c279 908 VisitAllPciInstances (SetPciIntLine);\r
2e70cf8a
GS
909\r
910 //\r
5218c279 911 // Set ACPI SCI_EN bit in PMCNTRL\r
2e70cf8a 912 //\r
5218c279 913 IoOr16 ((PciRead32 (Pmba) & ~BIT0) + 4, BIT0);\r
9b167857 914}\r
915\r
916\r
14b21de9 917EFI_STATUS\r
918EFIAPI\r
919ConnectRecursivelyIfPciMassStorage (\r
920 IN EFI_HANDLE Handle,\r
921 IN EFI_PCI_IO_PROTOCOL *Instance,\r
922 IN PCI_TYPE00 *PciHeader\r
923 )\r
924{\r
925 EFI_STATUS Status;\r
926 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
927 CHAR16 *DevPathStr;\r
928\r
929 if (IS_CLASS1 (PciHeader, PCI_CLASS_MASS_STORAGE)) {\r
930 DevicePath = NULL;\r
931 Status = gBS->HandleProtocol (\r
932 Handle,\r
933 &gEfiDevicePathProtocolGuid,\r
934 (VOID*)&DevicePath\r
935 );\r
936 if (EFI_ERROR (Status)) {\r
937 return Status;\r
938 }\r
939\r
940 //\r
941 // Print Device Path\r
942 //\r
943 DevPathStr = DevicePathToStr (DevicePath);\r
863986b3
RN
944 if (DevPathStr != NULL) {\r
945 DEBUG((\r
946 EFI_D_INFO,\r
947 "Found Mass Storage device: %s\n",\r
948 DevPathStr\r
949 ));\r
950 FreePool(DevPathStr);\r
951 }\r
14b21de9 952\r
953 Status = gBS->ConnectController (Handle, NULL, NULL, TRUE);\r
954 if (EFI_ERROR (Status)) {\r
955 return Status;\r
956 }\r
957\r
958 }\r
959\r
960 return EFI_SUCCESS;\r
961}\r
962\r
963\r
9607962d 964/**\r
965 This notification function is invoked when the\r
966 EMU Variable FVB has been changed.\r
967\r
968 @param Event The event that occured\r
969 @param Context For EFI compatiblity. Not used.\r
970\r
971**/\r
972VOID\r
973EFIAPI\r
974EmuVariablesUpdatedCallback (\r
975 IN EFI_EVENT Event,\r
976 IN VOID *Context\r
977 )\r
978{\r
979 DEBUG ((EFI_D_INFO, "EmuVariablesUpdatedCallback\n"));\r
980 UpdateNvVarsOnFileSystem ();\r
981}\r
982\r
983\r
14b21de9 984EFI_STATUS\r
985EFIAPI\r
986VisitingFileSystemInstance (\r
987 IN EFI_HANDLE Handle,\r
988 IN VOID *Instance,\r
989 IN VOID *Context\r
990 )\r
991{\r
992 EFI_STATUS Status;\r
993 STATIC BOOLEAN ConnectedToFileSystem = FALSE;\r
994\r
995 if (ConnectedToFileSystem) {\r
996 return EFI_ALREADY_STARTED;\r
997 }\r
998\r
999 Status = ConnectNvVarsToFileSystem (Handle);\r
1000 if (EFI_ERROR (Status)) {\r
1001 return Status;\r
1002 }\r
1003\r
1004 ConnectedToFileSystem = TRUE;\r
9607962d 1005 mEmuVariableEvent =\r
1006 EfiCreateProtocolNotifyEvent (\r
1007 &gEfiDevicePathProtocolGuid,\r
1008 TPL_CALLBACK,\r
1009 EmuVariablesUpdatedCallback,\r
1010 NULL,\r
1011 &mEmuVariableEventReg\r
1012 );\r
1013 PcdSet64 (PcdEmuVariableEvent, (UINT64)(UINTN) mEmuVariableEvent);\r
1014\r
14b21de9 1015 return EFI_SUCCESS;\r
1016}\r
1017\r
1018\r
1019VOID\r
1020PlatformBdsRestoreNvVarsFromHardDisk (\r
1021 )\r
1022{\r
1023 VisitAllPciInstances (ConnectRecursivelyIfPciMassStorage);\r
1024 VisitAllInstancesOfProtocol (\r
1025 &gEfiSimpleFileSystemProtocolGuid,\r
1026 VisitingFileSystemInstance,\r
1027 NULL\r
1028 );\r
3d131d1a 1029\r
14b21de9 1030}\r
1031\r
1032\r
49ba9447 1033VOID\r
1034PlatformBdsConnectSequence (\r
1035 VOID\r
1036 )\r
1037/*++\r
1038\r
1039Routine Description:\r
1040\r
1041 Connect with predeined platform connect sequence,\r
1042 the OEM/IBV can customize with their own connect sequence.\r
1043\r
1044Arguments:\r
1045\r
1046 None.\r
1047\r
1048Returns:\r
1049\r
1050 None.\r
1051\r
1052--*/\r
1053{\r
1054 UINTN Index;\r
1055\r
1056 DEBUG ((EFI_D_INFO, "PlatformBdsConnectSequence\n"));\r
1057\r
1058 Index = 0;\r
1059\r
1060 //\r
1061 // Here we can get the customized platform connect sequence\r
1062 // Notes: we can connect with new variable which record the\r
1063 // last time boots connect device path sequence\r
1064 //\r
1065 while (gPlatformConnectSequence[Index] != NULL) {\r
1066 //\r
1067 // Build the platform boot option\r
1068 //\r
1069 BdsLibConnectDevicePath (gPlatformConnectSequence[Index]);\r
1070 Index++;\r
1071 }\r
1072\r
1073 //\r
1074 // Just use the simple policy to connect all devices\r
1075 //\r
1076 BdsLibConnectAll ();\r
1077\r
2e70cf8a 1078 PciAcpiInitialization ();\r
40f2c454 1079\r
1080 //\r
1081 // Clear the logo after all devices are connected.\r
1082 //\r
1083 gST->ConOut->ClearScreen (gST->ConOut);\r
49ba9447 1084}\r
1085\r
1086VOID\r
1087PlatformBdsGetDriverOption (\r
1088 IN OUT LIST_ENTRY *BdsDriverLists\r
1089 )\r
1090/*++\r
1091\r
1092Routine Description:\r
1093\r
1094 Load the predefined driver option, OEM/IBV can customize this\r
1095 to load their own drivers\r
1096\r
1097Arguments:\r
1098\r
1099 BdsDriverLists - The header of the driver option link list.\r
1100\r
1101Returns:\r
1102\r
1103 None.\r
1104\r
1105--*/\r
1106{\r
1107 DEBUG ((EFI_D_INFO, "PlatformBdsGetDriverOption\n"));\r
1108 return;\r
1109}\r
1110\r
1111VOID\r
1112PlatformBdsDiagnostics (\r
1113 IN EXTENDMEM_COVERAGE_LEVEL MemoryTestLevel,\r
d18476d0 1114 IN BOOLEAN QuietBoot,\r
1115 IN BASEM_MEMORY_TEST BaseMemoryTest\r
49ba9447 1116 )\r
1117/*++\r
1118\r
1119Routine Description:\r
1120\r
1121 Perform the platform diagnostic, such like test memory. OEM/IBV also\r
1122 can customize this fuction to support specific platform diagnostic.\r
1123\r
1124Arguments:\r
1125\r
1126 MemoryTestLevel - The memory test intensive level\r
1127\r
1128 QuietBoot - Indicate if need to enable the quiet boot\r
1129\r
d18476d0 1130 BaseMemoryTest - A pointer to BaseMemoryTest()\r
1131\r
49ba9447 1132Returns:\r
1133\r
1134 None.\r
1135\r
1136--*/\r
1137{\r
1138 EFI_STATUS Status;\r
1139\r
1140 DEBUG ((EFI_D_INFO, "PlatformBdsDiagnostics\n"));\r
1141\r
1142 //\r
1143 // Here we can decide if we need to show\r
1144 // the diagnostics screen\r
1145 // Notes: this quiet boot code should be remove\r
1146 // from the graphic lib\r
1147 //\r
1148 if (QuietBoot) {\r
d46f3632 1149 EnableQuietBoot (PcdGetPtr(PcdLogoFile));\r
49ba9447 1150 //\r
1151 // Perform system diagnostic\r
1152 //\r
d18476d0 1153 Status = BaseMemoryTest (MemoryTestLevel);\r
49ba9447 1154 if (EFI_ERROR (Status)) {\r
1155 DisableQuietBoot ();\r
1156 }\r
1157\r
1158 return ;\r
1159 }\r
1160 //\r
1161 // Perform system diagnostic\r
1162 //\r
d18476d0 1163 Status = BaseMemoryTest (MemoryTestLevel);\r
49ba9447 1164}\r
1165\r
1166\r
9d7051b7
LE
1167/**\r
1168 Save the S3 boot script.\r
1169\r
1170 Note that we trigger DxeSmmReadyToLock here -- otherwise the script wouldn't\r
1171 be saved actually. Triggering this protocol installation event in turn locks\r
1172 down SMM, so no further changes to LockBoxes or SMRAM are possible\r
1173 afterwards.\r
1174**/\r
1175STATIC\r
1176VOID\r
1177SaveS3BootScript (\r
1178 VOID\r
1179 )\r
1180{\r
1181 EFI_STATUS Status;\r
1182 EFI_S3_SAVE_STATE_PROTOCOL *BootScript;\r
1183 EFI_HANDLE Handle;\r
1184 STATIC CONST UINT8 Info[] = { 0xDE, 0xAD, 0xBE, 0xEF };\r
1185\r
1186 Status = gBS->LocateProtocol (&gEfiS3SaveStateProtocolGuid, NULL,\r
1187 (VOID **) &BootScript);\r
1188 ASSERT_EFI_ERROR (Status);\r
1189\r
1190 //\r
1191 // Despite the opcode documentation in the PI spec, the protocol\r
1192 // implementation embeds a deep copy of the info in the boot script, rather\r
1193 // than storing just a pointer to runtime or NVS storage.\r
1194 //\r
1195 Status = BootScript->Write(BootScript, EFI_BOOT_SCRIPT_INFORMATION_OPCODE,\r
1196 (UINT32) sizeof Info,\r
1197 (EFI_PHYSICAL_ADDRESS)(UINTN) &Info);\r
1198 ASSERT_EFI_ERROR (Status);\r
1199\r
1200 Handle = NULL;\r
1201 Status = gBS->InstallProtocolInterface (&Handle,\r
1202 &gEfiDxeSmmReadyToLockProtocolGuid, EFI_NATIVE_INTERFACE,\r
1203 NULL);\r
1204 ASSERT_EFI_ERROR (Status);\r
1205}\r
1206\r
1207\r
49ba9447 1208VOID\r
1209EFIAPI\r
1210PlatformBdsPolicyBehavior (\r
49ba9447 1211 IN OUT LIST_ENTRY *DriverOptionList,\r
d18476d0 1212 IN OUT LIST_ENTRY *BootOptionList,\r
1213 IN PROCESS_CAPSULES ProcessCapsules,\r
1214 IN BASEM_MEMORY_TEST BaseMemoryTest\r
49ba9447 1215 )\r
1216/*++\r
1217\r
1218Routine Description:\r
1219\r
1220 The function will excute with as the platform policy, current policy\r
1221 is driven by boot mode. IBV/OEM can customize this code for their specific\r
1222 policy action.\r
1223\r
1224Arguments:\r
1225\r
49ba9447 1226 DriverOptionList - The header of the driver option link list\r
1227\r
1228 BootOptionList - The header of the boot option link list\r
1229\r
d18476d0 1230 ProcessCapsules - A pointer to ProcessCapsules()\r
1231\r
1232 BaseMemoryTest - A pointer to BaseMemoryTest()\r
1233\r
49ba9447 1234Returns:\r
1235\r
1236 None.\r
1237\r
1238--*/\r
1239{\r
1240 EFI_STATUS Status;\r
370ec7f1 1241 EFI_BOOT_MODE BootMode;\r
49ba9447 1242\r
1243 DEBUG ((EFI_D_INFO, "PlatformBdsPolicyBehavior\n"));\r
1244\r
2c34f3bc
LE
1245 VisitAllInstancesOfProtocol (&gEfiPciRootBridgeIoProtocolGuid,\r
1246 ConnectRootBridge, NULL);\r
14b21de9 1247\r
0f6ff51d
LE
1248 //\r
1249 // Signal the ACPI platform driver that it can download QEMU ACPI tables.\r
1250 //\r
1251 EfiEventGroupSignal (&gRootBridgesConnectedEventGroupGuid);\r
1252\r
896352e5
LE
1253 //\r
1254 // We can't signal End-of-Dxe earlier than this. Namely, End-of-Dxe triggers\r
1255 // the preparation of S3 system information. That logic has a hard dependency\r
1256 // on the presence of the FACS ACPI table. Since our ACPI tables are only\r
1257 // installed after PCI enumeration completes, we must not trigger the S3 save\r
1258 // earlier, hence we can't signal End-of-Dxe earlier.\r
1259 //\r
36e8e699 1260 EfiEventGroupSignal (&gEfiEndOfDxeEventGroupGuid);\r
896352e5 1261\r
9d7051b7
LE
1262 if (QemuFwCfgS3Enabled ()) {\r
1263 //\r
1264 // Save the boot script too. Note that this requires/includes emitting the\r
1265 // DxeSmmReadyToLock event, which in turn locks down SMM.\r
1266 //\r
1267 SaveS3BootScript ();\r
1268 }\r
1269\r
2590861a
LE
1270 if (PcdGetBool (PcdOvmfFlashVariablesEnable)) {\r
1271 DEBUG ((EFI_D_INFO, "PlatformBdsPolicyBehavior: not restoring NvVars "\r
1272 "from disk since flash variables appear to be supported.\n"));\r
1273 } else {\r
1274 //\r
1275 // Try to restore variables from the hard disk early so\r
1276 // they can be used for the other BDS connect operations.\r
1277 //\r
1278 PlatformBdsRestoreNvVarsFromHardDisk ();\r
1279 }\r
14b21de9 1280\r
49ba9447 1281 //\r
1282 // Load the driver option as the driver option list\r
1283 //\r
1284 PlatformBdsGetDriverOption (DriverOptionList);\r
1285\r
1286 //\r
1287 // Get current Boot Mode\r
1288 //\r
370ec7f1 1289 Status = BdsLibGetBootMode (&BootMode);\r
1290 DEBUG ((EFI_D_ERROR, "Boot Mode:%x\n", BootMode));\r
49ba9447 1291\r
1292 //\r
1293 // Go the different platform policy with different boot mode\r
1294 // Notes: this part code can be change with the table policy\r
1295 //\r
370ec7f1 1296 ASSERT (BootMode == BOOT_WITH_FULL_CONFIGURATION);\r
49ba9447 1297 //\r
1298 // Connect platform console\r
1299 //\r
1300 Status = PlatformBdsConnectConsole (gPlatformConsole);\r
1301 if (EFI_ERROR (Status)) {\r
1302 //\r
1303 // Here OEM/IBV can customize with defined action\r
1304 //\r
1305 PlatformBdsNoConsoleAction ();\r
1306 }\r
b1220e28 1307\r
49ba9447 1308 //\r
1309 // Memory test and Logo show\r
1310 //\r
d18476d0 1311 PlatformBdsDiagnostics (IGNORE, TRUE, BaseMemoryTest);\r
49ba9447 1312\r
1313 //\r
1314 // Perform some platform specific connect sequence\r
1315 //\r
1316 PlatformBdsConnectSequence ();\r
1317\r
52fba289 1318 //\r
1319 // Process QEMU's -kernel command line option\r
1320 //\r
1321 TryRunningQemuKernel ();\r
1322\r
49ba9447 1323 DEBUG ((EFI_D_INFO, "BdsLibConnectAll\n"));\r
1324 BdsLibConnectAll ();\r
1325 BdsLibEnumerateAllBootOption (BootOptionList);\r
1326\r
2cd086a6 1327 SetBootOrderFromQemu (BootOptionList);\r
49ba9447 1328 //\r
de5ae37b
LE
1329 // The BootOrder variable may have changed, reload the in-memory list with\r
1330 // it.\r
49ba9447 1331 //\r
de5ae37b 1332 BdsLibBuildOptionFromVar (BootOptionList, L"BootOrder");\r
49ba9447 1333\r
ea444a3e 1334 PlatformBdsEnterFrontPage (GetFrontPageTimeoutFromQemu(), TRUE);\r
49ba9447 1335}\r
1336\r
1337VOID\r
1338EFIAPI\r
1339PlatformBdsBootSuccess (\r
1340 IN BDS_COMMON_OPTION *Option\r
1341 )\r
1342/*++\r
1343\r
1344Routine Description:\r
1345\r
1346 Hook point after a boot attempt succeeds. We don't expect a boot option to\r
1347 return, so the EFI 1.0 specification defines that you will default to an\r
1348 interactive mode and stop processing the BootOrder list in this case. This\r
1349 is alos a platform implementation and can be customized by IBV/OEM.\r
1350\r
1351Arguments:\r
1352\r
1353 Option - Pointer to Boot Option that succeeded to boot.\r
1354\r
1355Returns:\r
1356\r
1357 None.\r
1358\r
1359--*/\r
1360{\r
1361 CHAR16 *TmpStr;\r
1362\r
1363 DEBUG ((EFI_D_INFO, "PlatformBdsBootSuccess\n"));\r
1364 //\r
1365 // If Boot returned with EFI_SUCCESS and there is not in the boot device\r
1366 // select loop then we need to pop up a UI and wait for user input.\r
1367 //\r
1368 TmpStr = Option->StatusString;\r
1369 if (TmpStr != NULL) {\r
1370 BdsLibOutputStrings (gST->ConOut, TmpStr, Option->Description, L"\n\r", NULL);\r
1371 FreePool (TmpStr);\r
1372 }\r
1373}\r
1374\r
1375VOID\r
1376EFIAPI\r
1377PlatformBdsBootFail (\r
1378 IN BDS_COMMON_OPTION *Option,\r
1379 IN EFI_STATUS Status,\r
1380 IN CHAR16 *ExitData,\r
1381 IN UINTN ExitDataSize\r
1382 )\r
1383/*++\r
1384\r
1385Routine Description:\r
1386\r
1387 Hook point after a boot attempt fails.\r
1388\r
1389Arguments:\r
1390\r
1391 Option - Pointer to Boot Option that failed to boot.\r
1392\r
1393 Status - Status returned from failed boot.\r
1394\r
1395 ExitData - Exit data returned from failed boot.\r
1396\r
1397 ExitDataSize - Exit data size returned from failed boot.\r
1398\r
1399Returns:\r
1400\r
1401 None.\r
1402\r
1403--*/\r
1404{\r
1405 CHAR16 *TmpStr;\r
1406\r
1407 DEBUG ((EFI_D_INFO, "PlatformBdsBootFail\n"));\r
1408\r
1409 //\r
1410 // If Boot returned with failed status then we need to pop up a UI and wait\r
1411 // for user input.\r
1412 //\r
1413 TmpStr = Option->StatusString;\r
1414 if (TmpStr != NULL) {\r
1415 BdsLibOutputStrings (gST->ConOut, TmpStr, Option->Description, L"\n\r", NULL);\r
1416 FreePool (TmpStr);\r
1417 }\r
1418}\r
1419\r
1420EFI_STATUS\r
1421PlatformBdsNoConsoleAction (\r
1422 VOID\r
1423 )\r
1424/*++\r
1425\r
1426Routine Description:\r
1427\r
1428 This function is remained for IBV/OEM to do some platform action,\r
1429 if there no console device can be connected.\r
1430\r
1431Arguments:\r
1432\r
1433 None.\r
1434\r
1435Returns:\r
1436\r
1437 EFI_SUCCESS - Direct return success now.\r
1438\r
1439--*/\r
1440{\r
1441 DEBUG ((EFI_D_INFO, "PlatformBdsNoConsoleAction\n"));\r
1442 return EFI_SUCCESS;\r
1443}\r
1444\r
24cdd14e 1445VOID\r
49ba9447 1446EFIAPI\r
1447PlatformBdsLockNonUpdatableFlash (\r
1448 VOID\r
1449 )\r
1450{\r
1451 DEBUG ((EFI_D_INFO, "PlatformBdsLockNonUpdatableFlash\n"));\r
24cdd14e 1452 return;\r
49ba9447 1453}\r
40f2c454 1454\r
1455\r
1456/**\r
1457 This notification function is invoked when an instance of the\r
1458 EFI_DEVICE_PATH_PROTOCOL is produced.\r
1459\r
1460 @param Event The event that occured\r
1461 @param Context For EFI compatiblity. Not used.\r
1462\r
1463**/\r
1464VOID\r
1465EFIAPI\r
1466NotifyDevPath (\r
1467 IN EFI_EVENT Event,\r
1468 IN VOID *Context\r
1469 )\r
1470{\r
1471 EFI_HANDLE Handle;\r
1472 EFI_STATUS Status;\r
1473 UINTN BufferSize;\r
1474 EFI_DEVICE_PATH_PROTOCOL *DevPathNode;\r
1475 ATAPI_DEVICE_PATH *Atapi;\r
1476\r
1477 //\r
1478 // Examine all new handles\r
1479 //\r
1480 for (;;) {\r
1481 //\r
1482 // Get the next handle\r
1483 //\r
1484 BufferSize = sizeof (Handle);\r
1485 Status = gBS->LocateHandle (\r
1486 ByRegisterNotify,\r
1487 NULL,\r
1488 mEfiDevPathNotifyReg,\r
1489 &BufferSize,\r
1490 &Handle\r
1491 );\r
1492\r
1493 //\r
1494 // If not found, we're done\r
1495 //\r
1496 if (EFI_NOT_FOUND == Status) {\r
1497 break;\r
1498 }\r
1499\r
1500 if (EFI_ERROR (Status)) {\r
1501 continue;\r
1502 }\r
1503\r
1504 //\r
1505 // Get the DevicePath protocol on that handle\r
1506 //\r
1507 Status = gBS->HandleProtocol (Handle, &gEfiDevicePathProtocolGuid, (VOID **)&DevPathNode);\r
1508 ASSERT_EFI_ERROR (Status);\r
1509\r
1510 while (!IsDevicePathEnd (DevPathNode)) {\r
1511 //\r
1512 // Find the handler to dump this device path node\r
1513 //\r
1514 if (\r
1515 (DevicePathType(DevPathNode) == MESSAGING_DEVICE_PATH) &&\r
1516 (DevicePathSubType(DevPathNode) == MSG_ATAPI_DP)\r
1517 ) {\r
1518 Atapi = (ATAPI_DEVICE_PATH*) DevPathNode;\r
1519 PciOr16 (\r
1520 PCI_LIB_ADDRESS (\r
1521 0,\r
1522 1,\r
1523 1,\r
1524 (Atapi->PrimarySecondary == 1) ? 0x42: 0x40\r
1525 ),\r
1526 BIT15\r
1527 );\r
1528 }\r
1529\r
1530 //\r
1531 // Next device path node\r
1532 //\r
1533 DevPathNode = NextDevicePathNode (DevPathNode);\r
1534 }\r
1535 }\r
1536\r
1537 return;\r
1538}\r
1539\r
1540\r
1541VOID\r
1542InstallDevicePathCallback (\r
1543 VOID\r
1544 )\r
1545{\r
1546 DEBUG ((EFI_D_INFO, "Registered NotifyDevPath Event\n"));\r
1547 mEfiDevPathEvent = EfiCreateProtocolNotifyEvent (\r
1548 &gEfiDevicePathProtocolGuid,\r
1549 TPL_CALLBACK,\r
1550 NotifyDevPath,\r
1551 NULL,\r
1552 &mEfiDevPathNotifyReg\r
1553 );\r
1554}\r
1555\r
24cdd14e
LG
1556/**\r
1557 Lock the ConsoleIn device in system table. All key\r
1558 presses will be ignored until the Password is typed in. The only way to\r
1559 disable the password is to type it in to a ConIn device.\r
1560\r
1561 @param Password Password used to lock ConIn device.\r
1562\r
1563 @retval EFI_SUCCESS lock the Console In Spliter virtual handle successfully.\r
1564 @retval EFI_UNSUPPORTED Password not found\r
1565\r
1566**/\r
1567EFI_STATUS\r
1568EFIAPI\r
1569LockKeyboards (\r
1570 IN CHAR16 *Password\r
1571 )\r
1572{\r
1573 return EFI_UNSUPPORTED;\r
1574}\r
5106d422 1575\r