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