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