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