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