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