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