]> git.proxmox.com Git - mirror_edk2.git/blob - OvmfPkg/Library/PlatformBootManagerLib/BdsPlatform.c
OvmfPkg/PlatformBootManagerLib: Follow PlatformBootManagerLib interfaces
[mirror_edk2.git] / OvmfPkg / Library / PlatformBootManagerLib / BdsPlatform.c
1 /** @file
2 Platform BDS customizations.
3
4 Copyright (c) 2004 - 2016, 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 PlatformBootManagerBeforeConsole (
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, "PlatformBootManagerBeforeConsole\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 PlatformBootManagerAfterConsole (
1253 VOID
1254 )
1255 /*++
1256
1257 Routine Description:
1258
1259 The function will excute with as the platform policy, current policy
1260 is driven by boot mode. IBV/OEM can customize this code for their specific
1261 policy action.
1262
1263 --*/
1264 {
1265 EFI_STATUS Status;
1266 EFI_BOOT_MODE BootMode;
1267
1268 DEBUG ((EFI_D_INFO, "PlatformBootManagerAfterConsole\n"));
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 This function is called each second during the boot manager waits the timeout.
1558
1559 @param TimeoutRemain The remaining timeout.
1560 **/
1561 VOID
1562 EFIAPI
1563 PlatformBootManagerWaitCallback (
1564 UINT16 TimeoutRemain
1565 )
1566 {
1567 }
1568
1569 /**
1570 Lock the ConsoleIn device in system table. All key
1571 presses will be ignored until the Password is typed in. The only way to
1572 disable the password is to type it in to a ConIn device.
1573
1574 @param Password Password used to lock ConIn device.
1575
1576 @retval EFI_SUCCESS lock the Console In Spliter virtual handle successfully.
1577 @retval EFI_UNSUPPORTED Password not found
1578
1579 **/
1580 EFI_STATUS
1581 EFIAPI
1582 LockKeyboards (
1583 IN CHAR16 *Password
1584 )
1585 {
1586 return EFI_UNSUPPORTED;
1587 }
1588