]> git.proxmox.com Git - mirror_edk2.git/blob - OvmfPkg/Library/PlatformBootManagerLibGrub/BdsPlatform.c
OvmfPkg: Apply uncrustify changes
[mirror_edk2.git] / OvmfPkg / Library / PlatformBootManagerLibGrub / BdsPlatform.c
1 /** @file
2 Platform BDS customizations.
3
4 Copyright (C) 2020 James Bottomley, IBM Corporation.
5 Copyright (c) 2004 - 2019, Intel Corporation. All rights reserved.<BR>
6 SPDX-License-Identifier: BSD-2-Clause-Patent
7
8 **/
9
10 #include "BdsPlatform.h"
11 #include <Guid/RootBridgesConnectedEventGroup.h>
12 #include <Protocol/FirmwareVolume2.h>
13 #include <Library/PlatformBmPrintScLib.h>
14 #include <Library/Tcg2PhysicalPresenceLib.h>
15
16 //
17 // Global data
18 //
19
20 VOID *mEfiDevPathNotifyReg;
21 EFI_EVENT mEfiDevPathEvent;
22 UINT16 mHostBridgeDevId;
23
24 //
25 // Table of host IRQs matching PCI IRQs A-D
26 // (for configuring PCI Interrupt Line register)
27 //
28 CONST UINT8 PciHostIrqs[] = {
29 0x0a, 0x0a, 0x0b, 0x0b
30 };
31
32 //
33 // Type definitions
34 //
35
36 typedef
37 EFI_STATUS
38 (EFIAPI *PROTOCOL_INSTANCE_CALLBACK)(
39 IN EFI_HANDLE Handle,
40 IN VOID *Instance,
41 IN VOID *Context
42 );
43
44 /**
45 @param[in] Handle - Handle of PCI device instance
46 @param[in] PciIo - PCI IO protocol instance
47 @param[in] Pci - PCI Header register block
48 **/
49 typedef
50 EFI_STATUS
51 (EFIAPI *VISIT_PCI_INSTANCE_CALLBACK)(
52 IN EFI_HANDLE Handle,
53 IN EFI_PCI_IO_PROTOCOL *PciIo,
54 IN PCI_TYPE00 *Pci
55 );
56
57 //
58 // Function prototypes
59 //
60
61 EFI_STATUS
62 VisitAllInstancesOfProtocol (
63 IN EFI_GUID *Id,
64 IN PROTOCOL_INSTANCE_CALLBACK CallBackFunction,
65 IN VOID *Context
66 );
67
68 EFI_STATUS
69 VisitAllPciInstancesOfProtocol (
70 IN VISIT_PCI_INSTANCE_CALLBACK CallBackFunction
71 );
72
73 VOID
74 InstallDevicePathCallback (
75 VOID
76 );
77
78 VOID
79 PlatformRegisterFvBootOption (
80 EFI_GUID *FileGuid,
81 CHAR16 *Description,
82 UINT32 Attributes
83 )
84 {
85 EFI_STATUS Status;
86 INTN OptionIndex;
87 EFI_BOOT_MANAGER_LOAD_OPTION NewOption;
88 EFI_BOOT_MANAGER_LOAD_OPTION *BootOptions;
89 UINTN BootOptionCount;
90 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH FileNode;
91 EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;
92 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
93
94 Status = gBS->HandleProtocol (
95 gImageHandle,
96 &gEfiLoadedImageProtocolGuid,
97 (VOID **)&LoadedImage
98 );
99 ASSERT_EFI_ERROR (Status);
100
101 EfiInitializeFwVolDevicepathNode (&FileNode, FileGuid);
102 DevicePath = DevicePathFromHandle (LoadedImage->DeviceHandle);
103 ASSERT (DevicePath != NULL);
104 DevicePath = AppendDevicePathNode (
105 DevicePath,
106 (EFI_DEVICE_PATH_PROTOCOL *)&FileNode
107 );
108 ASSERT (DevicePath != NULL);
109
110 Status = EfiBootManagerInitializeLoadOption (
111 &NewOption,
112 LoadOptionNumberUnassigned,
113 LoadOptionTypeBoot,
114 Attributes,
115 Description,
116 DevicePath,
117 NULL,
118 0
119 );
120 ASSERT_EFI_ERROR (Status);
121 FreePool (DevicePath);
122
123 BootOptions = EfiBootManagerGetLoadOptions (
124 &BootOptionCount,
125 LoadOptionTypeBoot
126 );
127
128 OptionIndex = EfiBootManagerFindLoadOption (
129 &NewOption,
130 BootOptions,
131 BootOptionCount
132 );
133
134 if (OptionIndex == -1) {
135 Status = EfiBootManagerAddLoadOptionVariable (&NewOption, MAX_UINTN);
136 ASSERT_EFI_ERROR (Status);
137 }
138
139 EfiBootManagerFreeLoadOption (&NewOption);
140 EfiBootManagerFreeLoadOptions (BootOptions, BootOptionCount);
141 }
142
143 /**
144 Remove all MemoryMapped(...)/FvFile(...) and Fv(...)/FvFile(...) boot options
145 whose device paths do not resolve exactly to an FvFile in the system.
146
147 Also strip out every boot option that is not an FvFile, meaning the system
148 can only boot either the Grub or (if built) the shell.
149
150 This removes any boot options that point to binaries built into the firmware
151 and have become stale due to any of the following:
152 - DXEFV's base address or size changed (historical),
153 - DXEFV's FvNameGuid changed,
154 - the FILE_GUID of the pointed-to binary changed,
155 - the referenced binary is no longer built into the firmware.
156
157 EfiBootManagerFindLoadOption() used in PlatformRegisterFvBootOption() only
158 avoids exact duplicates.
159 **/
160 VOID
161 RemoveStaleFvFileOptions (
162 VOID
163 )
164 {
165 EFI_BOOT_MANAGER_LOAD_OPTION *BootOptions;
166 UINTN BootOptionCount;
167 UINTN Index;
168
169 BootOptions = EfiBootManagerGetLoadOptions (
170 &BootOptionCount,
171 LoadOptionTypeBoot
172 );
173
174 for (Index = 0; Index < BootOptionCount; ++Index) {
175 EFI_DEVICE_PATH_PROTOCOL *Node1, *Node2, *SearchNode;
176 EFI_STATUS Status;
177 EFI_HANDLE FvHandle;
178
179 //
180 // If the device path starts with neither MemoryMapped(...) nor Fv(...),
181 // then delete the boot option.
182 //
183 Node1 = BootOptions[Index].FilePath;
184 if (!((DevicePathType (Node1) == HARDWARE_DEVICE_PATH) &&
185 (DevicePathSubType (Node1) == HW_MEMMAP_DP)) &&
186 !((DevicePathType (Node1) == MEDIA_DEVICE_PATH) &&
187 (DevicePathSubType (Node1) == MEDIA_PIWG_FW_VOL_DP)))
188 {
189 EfiBootManagerDeleteLoadOptionVariable (
190 BootOptions[Index].OptionNumber,
191 LoadOptionTypeBoot
192 );
193 continue;
194 }
195
196 //
197 // If the second device path node is not FvFile(...), then delete the boot
198 // option.
199 //
200 Node2 = NextDevicePathNode (Node1);
201 if ((DevicePathType (Node2) != MEDIA_DEVICE_PATH) ||
202 (DevicePathSubType (Node2) != MEDIA_PIWG_FW_FILE_DP))
203 {
204 EfiBootManagerDeleteLoadOptionVariable (
205 BootOptions[Index].OptionNumber,
206 LoadOptionTypeBoot
207 );
208 continue;
209 }
210
211 //
212 // Locate the Firmware Volume2 protocol instance that is denoted by the
213 // boot option. If this lookup fails (i.e., the boot option references a
214 // firmware volume that doesn't exist), then we'll proceed to delete the
215 // boot option.
216 //
217 SearchNode = Node1;
218 Status = gBS->LocateDevicePath (
219 &gEfiFirmwareVolume2ProtocolGuid,
220 &SearchNode,
221 &FvHandle
222 );
223
224 if (!EFI_ERROR (Status)) {
225 //
226 // The firmware volume was found; now let's see if it contains the FvFile
227 // identified by GUID.
228 //
229 EFI_FIRMWARE_VOLUME2_PROTOCOL *FvProtocol;
230 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *FvFileNode;
231 UINTN BufferSize;
232 EFI_FV_FILETYPE FoundType;
233 EFI_FV_FILE_ATTRIBUTES FileAttributes;
234 UINT32 AuthenticationStatus;
235
236 Status = gBS->HandleProtocol (
237 FvHandle,
238 &gEfiFirmwareVolume2ProtocolGuid,
239 (VOID **)&FvProtocol
240 );
241 ASSERT_EFI_ERROR (Status);
242
243 FvFileNode = (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *)Node2;
244 //
245 // Buffer==NULL means we request metadata only: BufferSize, FoundType,
246 // FileAttributes.
247 //
248 Status = FvProtocol->ReadFile (
249 FvProtocol,
250 &FvFileNode->FvFileName, // NameGuid
251 NULL, // Buffer
252 &BufferSize,
253 &FoundType,
254 &FileAttributes,
255 &AuthenticationStatus
256 );
257 if (!EFI_ERROR (Status)) {
258 //
259 // The FvFile was found. Keep the boot option.
260 //
261 continue;
262 }
263 }
264
265 //
266 // Delete the boot option.
267 //
268 Status = EfiBootManagerDeleteLoadOptionVariable (
269 BootOptions[Index].OptionNumber,
270 LoadOptionTypeBoot
271 );
272 DEBUG_CODE_BEGIN ();
273 CHAR16 *DevicePathString;
274
275 DevicePathString = ConvertDevicePathToText (
276 BootOptions[Index].FilePath,
277 FALSE,
278 FALSE
279 );
280 DEBUG ((
281 EFI_ERROR (Status) ? DEBUG_WARN : DEBUG_VERBOSE,
282 "%a: removing stale Boot#%04x %s: %r\n",
283 __FUNCTION__,
284 (UINT32)BootOptions[Index].OptionNumber,
285 DevicePathString == NULL ? L"<unavailable>" : DevicePathString,
286 Status
287 ));
288 if (DevicePathString != NULL) {
289 FreePool (DevicePathString);
290 }
291
292 DEBUG_CODE_END ();
293 }
294
295 EfiBootManagerFreeLoadOptions (BootOptions, BootOptionCount);
296 }
297
298 EFI_STATUS
299 EFIAPI
300 ConnectRootBridge (
301 IN EFI_HANDLE RootBridgeHandle,
302 IN VOID *Instance,
303 IN VOID *Context
304 );
305
306 STATIC
307 EFI_STATUS
308 EFIAPI
309 ConnectVirtioPciRng (
310 IN EFI_HANDLE Handle,
311 IN VOID *Instance,
312 IN VOID *Context
313 );
314
315 //
316 // BDS Platform Functions
317 //
318
319 /**
320 Do the platform init, can be customized by OEM/IBV
321
322 Possible things that can be done in PlatformBootManagerBeforeConsole:
323
324 > Update console variable: 1. include hot-plug devices;
325 > 2. Clear ConIn and add SOL for AMT
326 > Register new Driver#### or Boot####
327 > Register new Key####: e.g.: F12
328 > Signal ReadyToLock event
329 > Authentication action: 1. connect Auth devices;
330 > 2. Identify auto logon user.
331 **/
332 VOID
333 EFIAPI
334 PlatformBootManagerBeforeConsole (
335 VOID
336 )
337 {
338 EFI_HANDLE Handle;
339 EFI_STATUS Status;
340 UINT16 FrontPageTimeout;
341
342 FrontPageTimeout = 0;
343
344 DEBUG ((DEBUG_INFO, "PlatformBootManagerBeforeConsole\n"));
345 InstallDevicePathCallback ();
346
347 VisitAllInstancesOfProtocol (
348 &gEfiPciRootBridgeIoProtocolGuid,
349 ConnectRootBridge,
350 NULL
351 );
352
353 //
354 // Signal the ACPI platform driver that it can download QEMU ACPI tables.
355 //
356 EfiEventGroupSignal (&gRootBridgesConnectedEventGroupGuid);
357
358 //
359 // We can't signal End-of-Dxe earlier than this. Namely, End-of-Dxe triggers
360 // the preparation of S3 system information. That logic has a hard dependency
361 // on the presence of the FACS ACPI table. Since our ACPI tables are only
362 // installed after PCI enumeration completes, we must not trigger the S3 save
363 // earlier, hence we can't signal End-of-Dxe earlier.
364 //
365 EfiEventGroupSignal (&gEfiEndOfDxeEventGroupGuid);
366
367 // We need to connect all trusted consoles for TCG PP. Here we treat all
368 // consoles in OVMF to be trusted consoles.
369 PlatformInitializeConsole (gPlatformConsole);
370
371 //
372 // Process TPM PPI request
373 //
374 Tcg2PhysicalPresenceLibProcessRequest (NULL);
375
376 //
377 // Prevent further changes to LockBoxes or SMRAM.
378 // Any TPM 2 Physical Presence Interface opcode must be handled before.
379 //
380 Handle = NULL;
381 Status = gBS->InstallProtocolInterface (
382 &Handle,
383 &gEfiDxeSmmReadyToLockProtocolGuid,
384 EFI_NATIVE_INTERFACE,
385 NULL
386 );
387 ASSERT_EFI_ERROR (Status);
388
389 //
390 // Dispatch deferred images after EndOfDxe event and ReadyToLock
391 // installation.
392 //
393 EfiBootManagerDispatchDeferredImages ();
394
395 Status = gRT->SetVariable (
396 EFI_TIME_OUT_VARIABLE_NAME,
397 &gEfiGlobalVariableGuid,
398 (EFI_VARIABLE_NON_VOLATILE |
399 EFI_VARIABLE_BOOTSERVICE_ACCESS |
400 EFI_VARIABLE_RUNTIME_ACCESS),
401 sizeof FrontPageTimeout,
402 &FrontPageTimeout
403 );
404 //
405 // Install both VIRTIO_DEVICE_PROTOCOL and (dependent) EFI_RNG_PROTOCOL
406 // instances on Virtio PCI RNG devices.
407 //
408 VisitAllInstancesOfProtocol (
409 &gEfiPciIoProtocolGuid,
410 ConnectVirtioPciRng,
411 NULL
412 );
413 }
414
415 EFI_STATUS
416 EFIAPI
417 ConnectRootBridge (
418 IN EFI_HANDLE RootBridgeHandle,
419 IN VOID *Instance,
420 IN VOID *Context
421 )
422 {
423 EFI_STATUS Status;
424
425 //
426 // Make the PCI bus driver connect the root bridge, non-recursively. This
427 // will produce a number of child handles with PciIo on them.
428 //
429 Status = gBS->ConnectController (
430 RootBridgeHandle, // ControllerHandle
431 NULL, // DriverImageHandle
432 NULL, // RemainingDevicePath -- produce all
433 // children
434 FALSE // Recursive
435 );
436 return Status;
437 }
438
439 STATIC
440 EFI_STATUS
441 EFIAPI
442 ConnectVirtioPciRng (
443 IN EFI_HANDLE Handle,
444 IN VOID *Instance,
445 IN VOID *Context
446 )
447 {
448 EFI_PCI_IO_PROTOCOL *PciIo;
449 EFI_STATUS Status;
450 UINT16 VendorId;
451 UINT16 DeviceId;
452 UINT8 RevisionId;
453 BOOLEAN Virtio10;
454 UINT16 SubsystemId;
455
456 PciIo = Instance;
457
458 //
459 // Read and check VendorId.
460 //
461 Status = PciIo->Pci.Read (
462 PciIo,
463 EfiPciIoWidthUint16,
464 PCI_VENDOR_ID_OFFSET,
465 1,
466 &VendorId
467 );
468 if (EFI_ERROR (Status)) {
469 goto Error;
470 }
471
472 if (VendorId != VIRTIO_VENDOR_ID) {
473 return EFI_SUCCESS;
474 }
475
476 //
477 // Read DeviceId and RevisionId.
478 //
479 Status = PciIo->Pci.Read (
480 PciIo,
481 EfiPciIoWidthUint16,
482 PCI_DEVICE_ID_OFFSET,
483 1,
484 &DeviceId
485 );
486 if (EFI_ERROR (Status)) {
487 goto Error;
488 }
489
490 Status = PciIo->Pci.Read (
491 PciIo,
492 EfiPciIoWidthUint8,
493 PCI_REVISION_ID_OFFSET,
494 1,
495 &RevisionId
496 );
497 if (EFI_ERROR (Status)) {
498 goto Error;
499 }
500
501 //
502 // From DeviceId and RevisionId, determine whether the device is a
503 // modern-only Virtio 1.0 device. In case of Virtio 1.0, DeviceId can
504 // immediately be restricted to VIRTIO_SUBSYSTEM_ENTROPY_SOURCE, and
505 // SubsystemId will only play a sanity-check role. Otherwise, DeviceId can
506 // only be sanity-checked, and SubsystemId will decide.
507 //
508 if ((DeviceId == 0x1040 + VIRTIO_SUBSYSTEM_ENTROPY_SOURCE) &&
509 (RevisionId >= 0x01))
510 {
511 Virtio10 = TRUE;
512 } else if ((DeviceId >= 0x1000) && (DeviceId <= 0x103F) && (RevisionId == 0x00)) {
513 Virtio10 = FALSE;
514 } else {
515 return EFI_SUCCESS;
516 }
517
518 //
519 // Read and check SubsystemId as dictated by Virtio10.
520 //
521 Status = PciIo->Pci.Read (
522 PciIo,
523 EfiPciIoWidthUint16,
524 PCI_SUBSYSTEM_ID_OFFSET,
525 1,
526 &SubsystemId
527 );
528 if (EFI_ERROR (Status)) {
529 goto Error;
530 }
531
532 if ((Virtio10 && (SubsystemId >= 0x40)) ||
533 (!Virtio10 && (SubsystemId == VIRTIO_SUBSYSTEM_ENTROPY_SOURCE)))
534 {
535 Status = gBS->ConnectController (
536 Handle, // ControllerHandle
537 NULL, // DriverImageHandle -- connect all drivers
538 NULL, // RemainingDevicePath -- produce all child handles
539 FALSE // Recursive -- don't follow child handles
540 );
541 if (EFI_ERROR (Status)) {
542 goto Error;
543 }
544 }
545
546 return EFI_SUCCESS;
547
548 Error:
549 DEBUG ((DEBUG_ERROR, "%a: %r\n", __FUNCTION__, Status));
550 return Status;
551 }
552
553 /**
554 Add IsaKeyboard to ConIn; add IsaSerial to ConOut, ConIn, ErrOut.
555
556 @param[in] DeviceHandle Handle of the LPC Bridge device.
557
558 @retval EFI_SUCCESS Console devices on the LPC bridge have been added to
559 ConOut, ConIn, and ErrOut.
560
561 @return Error codes, due to EFI_DEVICE_PATH_PROTOCOL missing
562 from DeviceHandle.
563 **/
564 EFI_STATUS
565 PrepareLpcBridgeDevicePath (
566 IN EFI_HANDLE DeviceHandle
567 )
568 {
569 EFI_STATUS Status;
570 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
571 EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;
572 CHAR16 *DevPathStr;
573
574 DevicePath = NULL;
575 Status = gBS->HandleProtocol (
576 DeviceHandle,
577 &gEfiDevicePathProtocolGuid,
578 (VOID *)&DevicePath
579 );
580 if (EFI_ERROR (Status)) {
581 return Status;
582 }
583
584 TempDevicePath = DevicePath;
585
586 //
587 // Register Keyboard
588 //
589 DevicePath = AppendDevicePathNode (
590 DevicePath,
591 (EFI_DEVICE_PATH_PROTOCOL *)&gPnpPs2KeyboardDeviceNode
592 );
593
594 EfiBootManagerUpdateConsoleVariable (ConIn, DevicePath, NULL);
595
596 //
597 // Register COM1
598 //
599 DevicePath = TempDevicePath;
600 gPnp16550ComPortDeviceNode.UID = 0;
601
602 DevicePath = AppendDevicePathNode (
603 DevicePath,
604 (EFI_DEVICE_PATH_PROTOCOL *)&gPnp16550ComPortDeviceNode
605 );
606 DevicePath = AppendDevicePathNode (
607 DevicePath,
608 (EFI_DEVICE_PATH_PROTOCOL *)&gUartDeviceNode
609 );
610 DevicePath = AppendDevicePathNode (
611 DevicePath,
612 (EFI_DEVICE_PATH_PROTOCOL *)&gTerminalTypeDeviceNode
613 );
614
615 //
616 // Print Device Path
617 //
618 DevPathStr = ConvertDevicePathToText (DevicePath, FALSE, FALSE);
619 if (DevPathStr != NULL) {
620 DEBUG ((
621 DEBUG_INFO,
622 "BdsPlatform.c+%d: COM%d DevPath: %s\n",
623 DEBUG_LINE_NUMBER,
624 gPnp16550ComPortDeviceNode.UID + 1,
625 DevPathStr
626 ));
627 FreePool (DevPathStr);
628 }
629
630 EfiBootManagerUpdateConsoleVariable (ConOut, DevicePath, NULL);
631 EfiBootManagerUpdateConsoleVariable (ConIn, DevicePath, NULL);
632 EfiBootManagerUpdateConsoleVariable (ErrOut, DevicePath, NULL);
633
634 //
635 // Register COM2
636 //
637 DevicePath = TempDevicePath;
638 gPnp16550ComPortDeviceNode.UID = 1;
639
640 DevicePath = AppendDevicePathNode (
641 DevicePath,
642 (EFI_DEVICE_PATH_PROTOCOL *)&gPnp16550ComPortDeviceNode
643 );
644 DevicePath = AppendDevicePathNode (
645 DevicePath,
646 (EFI_DEVICE_PATH_PROTOCOL *)&gUartDeviceNode
647 );
648 DevicePath = AppendDevicePathNode (
649 DevicePath,
650 (EFI_DEVICE_PATH_PROTOCOL *)&gTerminalTypeDeviceNode
651 );
652
653 //
654 // Print Device Path
655 //
656 DevPathStr = ConvertDevicePathToText (DevicePath, FALSE, FALSE);
657 if (DevPathStr != NULL) {
658 DEBUG ((
659 DEBUG_INFO,
660 "BdsPlatform.c+%d: COM%d DevPath: %s\n",
661 DEBUG_LINE_NUMBER,
662 gPnp16550ComPortDeviceNode.UID + 1,
663 DevPathStr
664 ));
665 FreePool (DevPathStr);
666 }
667
668 EfiBootManagerUpdateConsoleVariable (ConOut, DevicePath, NULL);
669 EfiBootManagerUpdateConsoleVariable (ConIn, DevicePath, NULL);
670 EfiBootManagerUpdateConsoleVariable (ErrOut, DevicePath, NULL);
671
672 return EFI_SUCCESS;
673 }
674
675 EFI_STATUS
676 GetGopDevicePath (
677 IN EFI_DEVICE_PATH_PROTOCOL *PciDevicePath,
678 OUT EFI_DEVICE_PATH_PROTOCOL **GopDevicePath
679 )
680 {
681 UINTN Index;
682 EFI_STATUS Status;
683 EFI_HANDLE PciDeviceHandle;
684 EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;
685 EFI_DEVICE_PATH_PROTOCOL *TempPciDevicePath;
686 UINTN GopHandleCount;
687 EFI_HANDLE *GopHandleBuffer;
688
689 if ((PciDevicePath == NULL) || (GopDevicePath == NULL)) {
690 return EFI_INVALID_PARAMETER;
691 }
692
693 //
694 // Initialize the GopDevicePath to be PciDevicePath
695 //
696 *GopDevicePath = PciDevicePath;
697 TempPciDevicePath = PciDevicePath;
698
699 Status = gBS->LocateDevicePath (
700 &gEfiDevicePathProtocolGuid,
701 &TempPciDevicePath,
702 &PciDeviceHandle
703 );
704 if (EFI_ERROR (Status)) {
705 return Status;
706 }
707
708 //
709 // Try to connect this handle, so that GOP driver could start on this
710 // device and create child handles with GraphicsOutput Protocol installed
711 // on them, then we get device paths of these child handles and select
712 // them as possible console device.
713 //
714 gBS->ConnectController (PciDeviceHandle, NULL, NULL, FALSE);
715
716 Status = gBS->LocateHandleBuffer (
717 ByProtocol,
718 &gEfiGraphicsOutputProtocolGuid,
719 NULL,
720 &GopHandleCount,
721 &GopHandleBuffer
722 );
723 if (!EFI_ERROR (Status)) {
724 //
725 // Add all the child handles as possible Console Device
726 //
727 for (Index = 0; Index < GopHandleCount; Index++) {
728 Status = gBS->HandleProtocol (
729 GopHandleBuffer[Index],
730 &gEfiDevicePathProtocolGuid,
731 (VOID *)&TempDevicePath
732 );
733 if (EFI_ERROR (Status)) {
734 continue;
735 }
736
737 if (CompareMem (
738 PciDevicePath,
739 TempDevicePath,
740 GetDevicePathSize (PciDevicePath) - END_DEVICE_PATH_LENGTH
741 ) == 0)
742 {
743 //
744 // In current implementation, we only enable one of the child handles
745 // as console device, i.e. sotre one of the child handle's device
746 // path to variable "ConOut"
747 // In future, we could select all child handles to be console device
748 //
749
750 *GopDevicePath = TempDevicePath;
751
752 //
753 // Delete the PCI device's path that added by
754 // GetPlugInPciVgaDevicePath(). Add the integrity GOP device path.
755 //
756 EfiBootManagerUpdateConsoleVariable (ConOutDev, NULL, PciDevicePath);
757 EfiBootManagerUpdateConsoleVariable (ConOutDev, TempDevicePath, NULL);
758 }
759 }
760
761 gBS->FreePool (GopHandleBuffer);
762 }
763
764 return EFI_SUCCESS;
765 }
766
767 /**
768 Add PCI display to ConOut.
769
770 @param[in] DeviceHandle Handle of the PCI display device.
771
772 @retval EFI_SUCCESS The PCI display device has been added to ConOut.
773
774 @return Error codes, due to EFI_DEVICE_PATH_PROTOCOL missing
775 from DeviceHandle.
776 **/
777 EFI_STATUS
778 PreparePciDisplayDevicePath (
779 IN EFI_HANDLE DeviceHandle
780 )
781 {
782 EFI_STATUS Status;
783 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
784 EFI_DEVICE_PATH_PROTOCOL *GopDevicePath;
785
786 DevicePath = NULL;
787 GopDevicePath = NULL;
788 Status = gBS->HandleProtocol (
789 DeviceHandle,
790 &gEfiDevicePathProtocolGuid,
791 (VOID *)&DevicePath
792 );
793 if (EFI_ERROR (Status)) {
794 return Status;
795 }
796
797 GetGopDevicePath (DevicePath, &GopDevicePath);
798 DevicePath = GopDevicePath;
799
800 EfiBootManagerUpdateConsoleVariable (ConOut, DevicePath, NULL);
801
802 return EFI_SUCCESS;
803 }
804
805 /**
806 Add PCI Serial to ConOut, ConIn, ErrOut.
807
808 @param[in] DeviceHandle Handle of the PCI serial device.
809
810 @retval EFI_SUCCESS The PCI serial device has been added to ConOut, ConIn,
811 ErrOut.
812
813 @return Error codes, due to EFI_DEVICE_PATH_PROTOCOL missing
814 from DeviceHandle.
815 **/
816 EFI_STATUS
817 PreparePciSerialDevicePath (
818 IN EFI_HANDLE DeviceHandle
819 )
820 {
821 EFI_STATUS Status;
822 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
823
824 DevicePath = NULL;
825 Status = gBS->HandleProtocol (
826 DeviceHandle,
827 &gEfiDevicePathProtocolGuid,
828 (VOID *)&DevicePath
829 );
830 if (EFI_ERROR (Status)) {
831 return Status;
832 }
833
834 DevicePath = AppendDevicePathNode (
835 DevicePath,
836 (EFI_DEVICE_PATH_PROTOCOL *)&gUartDeviceNode
837 );
838 DevicePath = AppendDevicePathNode (
839 DevicePath,
840 (EFI_DEVICE_PATH_PROTOCOL *)&gTerminalTypeDeviceNode
841 );
842
843 EfiBootManagerUpdateConsoleVariable (ConOut, DevicePath, NULL);
844 EfiBootManagerUpdateConsoleVariable (ConIn, DevicePath, NULL);
845 EfiBootManagerUpdateConsoleVariable (ErrOut, DevicePath, NULL);
846
847 return EFI_SUCCESS;
848 }
849
850 EFI_STATUS
851 VisitAllInstancesOfProtocol (
852 IN EFI_GUID *Id,
853 IN PROTOCOL_INSTANCE_CALLBACK CallBackFunction,
854 IN VOID *Context
855 )
856 {
857 EFI_STATUS Status;
858 UINTN HandleCount;
859 EFI_HANDLE *HandleBuffer;
860 UINTN Index;
861 VOID *Instance;
862
863 //
864 // Start to check all the PciIo to find all possible device
865 //
866 HandleCount = 0;
867 HandleBuffer = NULL;
868 Status = gBS->LocateHandleBuffer (
869 ByProtocol,
870 Id,
871 NULL,
872 &HandleCount,
873 &HandleBuffer
874 );
875 if (EFI_ERROR (Status)) {
876 return Status;
877 }
878
879 for (Index = 0; Index < HandleCount; Index++) {
880 Status = gBS->HandleProtocol (HandleBuffer[Index], Id, &Instance);
881 if (EFI_ERROR (Status)) {
882 continue;
883 }
884
885 Status = (*CallBackFunction)(
886 HandleBuffer[Index],
887 Instance,
888 Context
889 );
890 }
891
892 gBS->FreePool (HandleBuffer);
893
894 return EFI_SUCCESS;
895 }
896
897 EFI_STATUS
898 EFIAPI
899 VisitingAPciInstance (
900 IN EFI_HANDLE Handle,
901 IN VOID *Instance,
902 IN VOID *Context
903 )
904 {
905 EFI_STATUS Status;
906 EFI_PCI_IO_PROTOCOL *PciIo;
907 PCI_TYPE00 Pci;
908
909 PciIo = (EFI_PCI_IO_PROTOCOL *)Instance;
910
911 //
912 // Check for all PCI device
913 //
914 Status = PciIo->Pci.Read (
915 PciIo,
916 EfiPciIoWidthUint32,
917 0,
918 sizeof (Pci) / sizeof (UINT32),
919 &Pci
920 );
921 if (EFI_ERROR (Status)) {
922 return Status;
923 }
924
925 return (*(VISIT_PCI_INSTANCE_CALLBACK)(UINTN)Context)(
926 Handle,
927 PciIo,
928 &Pci
929 );
930 }
931
932 EFI_STATUS
933 VisitAllPciInstances (
934 IN VISIT_PCI_INSTANCE_CALLBACK CallBackFunction
935 )
936 {
937 return VisitAllInstancesOfProtocol (
938 &gEfiPciIoProtocolGuid,
939 VisitingAPciInstance,
940 (VOID *)(UINTN)CallBackFunction
941 );
942 }
943
944 /**
945 Do platform specific PCI Device check and add them to
946 ConOut, ConIn, ErrOut.
947
948 @param[in] Handle - Handle of PCI device instance
949 @param[in] PciIo - PCI IO protocol instance
950 @param[in] Pci - PCI Header register block
951
952 @retval EFI_SUCCESS - PCI Device check and Console variable update
953 successfully.
954 @retval EFI_STATUS - PCI Device check or Console variable update fail.
955
956 **/
957 EFI_STATUS
958 EFIAPI
959 DetectAndPreparePlatformPciDevicePath (
960 IN EFI_HANDLE Handle,
961 IN EFI_PCI_IO_PROTOCOL *PciIo,
962 IN PCI_TYPE00 *Pci
963 )
964 {
965 EFI_STATUS Status;
966
967 Status = PciIo->Attributes (
968 PciIo,
969 EfiPciIoAttributeOperationEnable,
970 EFI_PCI_DEVICE_ENABLE,
971 NULL
972 );
973 ASSERT_EFI_ERROR (Status);
974
975 //
976 // Here we decide whether it is LPC Bridge
977 //
978 if ((IS_PCI_LPC (Pci)) ||
979 ((IS_PCI_ISA_PDECODE (Pci)) &&
980 (Pci->Hdr.VendorId == 0x8086) &&
981 (Pci->Hdr.DeviceId == 0x7000)
982 )
983 )
984 {
985 //
986 // Add IsaKeyboard to ConIn,
987 // add IsaSerial to ConOut, ConIn, ErrOut
988 //
989 DEBUG ((DEBUG_INFO, "Found LPC Bridge device\n"));
990 PrepareLpcBridgeDevicePath (Handle);
991 return EFI_SUCCESS;
992 }
993
994 //
995 // Here we decide which Serial device to enable in PCI bus
996 //
997 if (IS_PCI_16550SERIAL (Pci)) {
998 //
999 // Add them to ConOut, ConIn, ErrOut.
1000 //
1001 DEBUG ((DEBUG_INFO, "Found PCI 16550 SERIAL device\n"));
1002 PreparePciSerialDevicePath (Handle);
1003 return EFI_SUCCESS;
1004 }
1005
1006 //
1007 // Here we decide which display device to enable in PCI bus
1008 //
1009 if (IS_PCI_DISPLAY (Pci)) {
1010 //
1011 // Add them to ConOut.
1012 //
1013 DEBUG ((DEBUG_INFO, "Found PCI display device\n"));
1014 PreparePciDisplayDevicePath (Handle);
1015 return EFI_SUCCESS;
1016 }
1017
1018 return Status;
1019 }
1020
1021 /**
1022 Connect the predefined platform default console device.
1023
1024 Always try to find and enable PCI display devices.
1025
1026 @param[in] PlatformConsole Predefined platform default console device array.
1027 **/
1028 VOID
1029 PlatformInitializeConsole (
1030 IN PLATFORM_CONSOLE_CONNECT_ENTRY *PlatformConsole
1031 )
1032 {
1033 UINTN Index;
1034
1035 //
1036 // Do platform specific PCI Device check and add them to ConOut, ConIn,
1037 // ErrOut
1038 //
1039 VisitAllPciInstances (DetectAndPreparePlatformPciDevicePath);
1040
1041 //
1042 // Have chance to connect the platform default console,
1043 // the platform default console is the minimum device group
1044 // the platform should support
1045 //
1046 for (Index = 0; PlatformConsole[Index].DevicePath != NULL; ++Index) {
1047 //
1048 // Update the console variable with the connect type
1049 //
1050 if ((PlatformConsole[Index].ConnectType & CONSOLE_IN) == CONSOLE_IN) {
1051 EfiBootManagerUpdateConsoleVariable (
1052 ConIn,
1053 PlatformConsole[Index].DevicePath,
1054 NULL
1055 );
1056 }
1057
1058 if ((PlatformConsole[Index].ConnectType & CONSOLE_OUT) == CONSOLE_OUT) {
1059 EfiBootManagerUpdateConsoleVariable (
1060 ConOut,
1061 PlatformConsole[Index].DevicePath,
1062 NULL
1063 );
1064 }
1065
1066 if ((PlatformConsole[Index].ConnectType & STD_ERROR) == STD_ERROR) {
1067 EfiBootManagerUpdateConsoleVariable (
1068 ErrOut,
1069 PlatformConsole[Index].DevicePath,
1070 NULL
1071 );
1072 }
1073 }
1074 }
1075
1076 /**
1077 Configure PCI Interrupt Line register for applicable devices
1078 Ported from SeaBIOS, src/fw/pciinit.c, *_pci_slot_get_irq()
1079
1080 @param[in] Handle - Handle of PCI device instance
1081 @param[in] PciIo - PCI IO protocol instance
1082 @param[in] PciHdr - PCI Header register block
1083
1084 @retval EFI_SUCCESS - PCI Interrupt Line register configured successfully.
1085
1086 **/
1087 EFI_STATUS
1088 EFIAPI
1089 SetPciIntLine (
1090 IN EFI_HANDLE Handle,
1091 IN EFI_PCI_IO_PROTOCOL *PciIo,
1092 IN PCI_TYPE00 *PciHdr
1093 )
1094 {
1095 EFI_DEVICE_PATH_PROTOCOL *DevPathNode;
1096 EFI_DEVICE_PATH_PROTOCOL *DevPath;
1097 UINTN RootSlot;
1098 UINTN Idx;
1099 UINT8 IrqLine;
1100 EFI_STATUS Status;
1101 UINT32 RootBusNumber;
1102
1103 Status = EFI_SUCCESS;
1104
1105 if (PciHdr->Device.InterruptPin != 0) {
1106 DevPathNode = DevicePathFromHandle (Handle);
1107 ASSERT (DevPathNode != NULL);
1108 DevPath = DevPathNode;
1109
1110 RootBusNumber = 0;
1111 if ((DevicePathType (DevPathNode) == ACPI_DEVICE_PATH) &&
1112 (DevicePathSubType (DevPathNode) == ACPI_DP) &&
1113 (((ACPI_HID_DEVICE_PATH *)DevPathNode)->HID == EISA_PNP_ID (0x0A03)))
1114 {
1115 RootBusNumber = ((ACPI_HID_DEVICE_PATH *)DevPathNode)->UID;
1116 }
1117
1118 //
1119 // Compute index into PciHostIrqs[] table by walking
1120 // the device path and adding up all device numbers
1121 //
1122 Status = EFI_NOT_FOUND;
1123 RootSlot = 0;
1124 Idx = PciHdr->Device.InterruptPin - 1;
1125 while (!IsDevicePathEnd (DevPathNode)) {
1126 if ((DevicePathType (DevPathNode) == HARDWARE_DEVICE_PATH) &&
1127 (DevicePathSubType (DevPathNode) == HW_PCI_DP))
1128 {
1129 Idx += ((PCI_DEVICE_PATH *)DevPathNode)->Device;
1130
1131 //
1132 // Unlike SeaBIOS, which starts climbing from the leaf device
1133 // up toward the root, we traverse the device path starting at
1134 // the root moving toward the leaf node.
1135 // The slot number of the top-level parent bridge is needed for
1136 // Q35 cases with more than 24 slots on the root bus.
1137 //
1138 if (Status != EFI_SUCCESS) {
1139 Status = EFI_SUCCESS;
1140 RootSlot = ((PCI_DEVICE_PATH *)DevPathNode)->Device;
1141 }
1142 }
1143
1144 DevPathNode = NextDevicePathNode (DevPathNode);
1145 }
1146
1147 if (EFI_ERROR (Status)) {
1148 return Status;
1149 }
1150
1151 if ((RootBusNumber == 0) && (RootSlot == 0)) {
1152 DEBUG ((
1153 DEBUG_ERROR,
1154 "%a: PCI host bridge (00:00.0) should have no interrupts!\n",
1155 __FUNCTION__
1156 ));
1157 ASSERT (FALSE);
1158 }
1159
1160 //
1161 // Final PciHostIrqs[] index calculation depends on the platform
1162 // and should match SeaBIOS src/fw/pciinit.c *_pci_slot_get_irq()
1163 //
1164 switch (mHostBridgeDevId) {
1165 case INTEL_82441_DEVICE_ID:
1166 Idx -= 1;
1167 break;
1168 case INTEL_Q35_MCH_DEVICE_ID:
1169 //
1170 // SeaBIOS contains the following comment:
1171 // "Slots 0-24 rotate slot:pin mapping similar to piix above, but
1172 // with a different starting index - see q35-acpi-dsdt.dsl.
1173 //
1174 // Slots 25-31 all use LNKA mapping (or LNKE, but A:D = E:H)"
1175 //
1176 if (RootSlot > 24) {
1177 //
1178 // in this case, subtract back out RootSlot from Idx
1179 // (SeaBIOS never adds it to begin with, but that would make our
1180 // device path traversal loop above too awkward)
1181 //
1182 Idx -= RootSlot;
1183 }
1184
1185 break;
1186 default:
1187 ASSERT (FALSE); // should never get here
1188 }
1189
1190 Idx %= ARRAY_SIZE (PciHostIrqs);
1191 IrqLine = PciHostIrqs[Idx];
1192
1193 DEBUG_CODE_BEGIN ();
1194 {
1195 CHAR16 *DevPathString;
1196 STATIC CHAR16 Fallback[] = L"<failed to convert>";
1197 UINTN Segment, Bus, Device, Function;
1198
1199 DevPathString = ConvertDevicePathToText (DevPath, FALSE, FALSE);
1200 if (DevPathString == NULL) {
1201 DevPathString = Fallback;
1202 }
1203
1204 Status = PciIo->GetLocation (PciIo, &Segment, &Bus, &Device, &Function);
1205 ASSERT_EFI_ERROR (Status);
1206
1207 DEBUG ((
1208 DEBUG_VERBOSE,
1209 "%a: [%02x:%02x.%x] %s -> 0x%02x\n",
1210 __FUNCTION__,
1211 (UINT32)Bus,
1212 (UINT32)Device,
1213 (UINT32)Function,
1214 DevPathString,
1215 IrqLine
1216 ));
1217
1218 if (DevPathString != Fallback) {
1219 FreePool (DevPathString);
1220 }
1221 }
1222 DEBUG_CODE_END ();
1223
1224 //
1225 // Set PCI Interrupt Line register for this device to PciHostIrqs[Idx]
1226 //
1227 Status = PciIo->Pci.Write (
1228 PciIo,
1229 EfiPciIoWidthUint8,
1230 PCI_INT_LINE_OFFSET,
1231 1,
1232 &IrqLine
1233 );
1234 }
1235
1236 return Status;
1237 }
1238
1239 VOID
1240 PciAcpiInitialization (
1241 )
1242 {
1243 UINTN Pmba;
1244
1245 //
1246 // Query Host Bridge DID to determine platform type
1247 //
1248 mHostBridgeDevId = PcdGet16 (PcdOvmfHostBridgePciDevId);
1249 switch (mHostBridgeDevId) {
1250 case INTEL_82441_DEVICE_ID:
1251 Pmba = POWER_MGMT_REGISTER_PIIX4 (PIIX4_PMBA);
1252 //
1253 // 00:01.0 ISA Bridge (PIIX4) LNK routing targets
1254 //
1255 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x60), 0x0b); // A
1256 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x61), 0x0b); // B
1257 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x62), 0x0a); // C
1258 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x63), 0x0a); // D
1259 break;
1260 case INTEL_Q35_MCH_DEVICE_ID:
1261 Pmba = POWER_MGMT_REGISTER_Q35 (ICH9_PMBASE);
1262 //
1263 // 00:1f.0 LPC Bridge (Q35) LNK routing targets
1264 //
1265 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x60), 0x0a); // A
1266 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x61), 0x0a); // B
1267 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x62), 0x0b); // C
1268 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x63), 0x0b); // D
1269 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x68), 0x0a); // E
1270 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x69), 0x0a); // F
1271 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x6a), 0x0b); // G
1272 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x6b), 0x0b); // H
1273 break;
1274 default:
1275 DEBUG ((
1276 DEBUG_ERROR,
1277 "%a: Unknown Host Bridge Device ID: 0x%04x\n",
1278 __FUNCTION__,
1279 mHostBridgeDevId
1280 ));
1281 ASSERT (FALSE);
1282 return;
1283 }
1284
1285 //
1286 // Initialize PCI_INTERRUPT_LINE for applicable present PCI devices
1287 //
1288 VisitAllPciInstances (SetPciIntLine);
1289
1290 //
1291 // Set ACPI SCI_EN bit in PMCNTRL
1292 //
1293 IoOr16 ((PciRead32 (Pmba) & ~BIT0) + 4, BIT0);
1294 }
1295
1296 EFI_STATUS
1297 EFIAPI
1298 ConnectRecursivelyIfPciMassStorage (
1299 IN EFI_HANDLE Handle,
1300 IN EFI_PCI_IO_PROTOCOL *Instance,
1301 IN PCI_TYPE00 *PciHeader
1302 )
1303 {
1304 EFI_STATUS Status;
1305 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
1306 CHAR16 *DevPathStr;
1307
1308 //
1309 // Recognize PCI Mass Storage
1310 //
1311 if (IS_CLASS1 (PciHeader, PCI_CLASS_MASS_STORAGE)) {
1312 DevicePath = NULL;
1313 Status = gBS->HandleProtocol (
1314 Handle,
1315 &gEfiDevicePathProtocolGuid,
1316 (VOID *)&DevicePath
1317 );
1318 if (EFI_ERROR (Status)) {
1319 return Status;
1320 }
1321
1322 //
1323 // Print Device Path
1324 //
1325 DevPathStr = ConvertDevicePathToText (DevicePath, FALSE, FALSE);
1326 if (DevPathStr != NULL) {
1327 DEBUG ((
1328 DEBUG_INFO,
1329 "Found Mass Storage device: %s\n",
1330 DevPathStr
1331 ));
1332 FreePool (DevPathStr);
1333 }
1334
1335 Status = gBS->ConnectController (Handle, NULL, NULL, TRUE);
1336 if (EFI_ERROR (Status)) {
1337 return Status;
1338 }
1339 }
1340
1341 return EFI_SUCCESS;
1342 }
1343
1344 /**
1345 Connect with predefined platform connect sequence.
1346
1347 The OEM/IBV can customize with their own connect sequence.
1348 **/
1349 VOID
1350 PlatformBdsConnectSequence (
1351 VOID
1352 )
1353 {
1354 UINTN Index;
1355
1356 DEBUG ((DEBUG_INFO, "PlatformBdsConnectSequence\n"));
1357
1358 Index = 0;
1359
1360 //
1361 // Here we can get the customized platform connect sequence
1362 // Notes: we can connect with new variable which record the
1363 // last time boots connect device path sequence
1364 //
1365 while (gPlatformConnectSequence[Index] != NULL) {
1366 //
1367 // Build the platform boot option
1368 //
1369 EfiBootManagerConnectDevicePath (gPlatformConnectSequence[Index], NULL);
1370 Index++;
1371 }
1372
1373 EfiBootManagerConnectAll ();
1374 }
1375
1376 /**
1377 Do the platform specific action after the console is ready
1378
1379 Possible things that can be done in PlatformBootManagerAfterConsole:
1380
1381 > Console post action:
1382 > Dynamically switch output mode from 100x31 to 80x25 for certain senarino
1383 > Signal console ready platform customized event
1384 > Run diagnostics like memory testing
1385 > Connect certain devices
1386 > Dispatch aditional option roms
1387 > Special boot: e.g.: USB boot, enter UI
1388 **/
1389 VOID
1390 EFIAPI
1391 PlatformBootManagerAfterConsole (
1392 VOID
1393 )
1394 {
1395 EFI_BOOT_MODE BootMode;
1396
1397 DEBUG ((DEBUG_INFO, "PlatformBootManagerAfterConsole\n"));
1398
1399 //
1400 // Get current Boot Mode
1401 //
1402 BootMode = GetBootModeHob ();
1403 DEBUG ((DEBUG_INFO, "Boot Mode:%x\n", BootMode));
1404
1405 //
1406 // Go the different platform policy with different boot mode
1407 // Notes: this part code can be change with the table policy
1408 //
1409 ASSERT (BootMode == BOOT_WITH_FULL_CONFIGURATION);
1410
1411 //
1412 // Logo show
1413 //
1414 BootLogoEnableLogo ();
1415
1416 //
1417 // Set PCI Interrupt Line registers and ACPI SCI_EN
1418 //
1419 PciAcpiInitialization ();
1420
1421 //
1422 // Process QEMU's -kernel command line option
1423 //
1424 TryRunningQemuKernel ();
1425
1426 //
1427 // Perform some platform specific connect sequence
1428 //
1429 PlatformBdsConnectSequence ();
1430
1431 EfiBootManagerRefreshAllBootOption ();
1432
1433 //
1434 // Register UEFI Shell (Will be removed if the Shell isn't built
1435 // which is the default)
1436 //
1437 PlatformRegisterFvBootOption (
1438 &gUefiShellFileGuid,
1439 L"EFI Internal Shell",
1440 LOAD_OPTION_ACTIVE
1441 );
1442
1443 //
1444 // Register Grub
1445 //
1446 PlatformRegisterFvBootOption (
1447 &gGrubFileGuid,
1448 L"Grub Bootloader",
1449 LOAD_OPTION_ACTIVE
1450 );
1451
1452 RemoveStaleFvFileOptions ();
1453
1454 PlatformBmPrintScRegisterHandler ();
1455 }
1456
1457 /**
1458 This notification function is invoked when an instance of the
1459 EFI_DEVICE_PATH_PROTOCOL is produced.
1460
1461 @param Event The event that occurred
1462 @param Context For EFI compatibility. Not used.
1463
1464 **/
1465 VOID
1466 EFIAPI
1467 NotifyDevPath (
1468 IN EFI_EVENT Event,
1469 IN VOID *Context
1470 )
1471 {
1472 EFI_HANDLE Handle;
1473 EFI_STATUS Status;
1474 UINTN BufferSize;
1475 EFI_DEVICE_PATH_PROTOCOL *DevPathNode;
1476 ATAPI_DEVICE_PATH *Atapi;
1477
1478 //
1479 // Examine all new handles
1480 //
1481 for ( ; ;) {
1482 //
1483 // Get the next handle
1484 //
1485 BufferSize = sizeof (Handle);
1486 Status = gBS->LocateHandle (
1487 ByRegisterNotify,
1488 NULL,
1489 mEfiDevPathNotifyReg,
1490 &BufferSize,
1491 &Handle
1492 );
1493
1494 //
1495 // If not found, we're done
1496 //
1497 if (EFI_NOT_FOUND == Status) {
1498 break;
1499 }
1500
1501 if (EFI_ERROR (Status)) {
1502 continue;
1503 }
1504
1505 //
1506 // Get the DevicePath protocol on that handle
1507 //
1508 Status = gBS->HandleProtocol (
1509 Handle,
1510 &gEfiDevicePathProtocolGuid,
1511 (VOID **)&DevPathNode
1512 );
1513 ASSERT_EFI_ERROR (Status);
1514
1515 while (!IsDevicePathEnd (DevPathNode)) {
1516 //
1517 // Find the handler to dump this device path node
1518 //
1519 if (
1520 (DevicePathType (DevPathNode) == MESSAGING_DEVICE_PATH) &&
1521 (DevicePathSubType (DevPathNode) == MSG_ATAPI_DP)
1522 )
1523 {
1524 Atapi = (ATAPI_DEVICE_PATH *)DevPathNode;
1525 PciOr16 (
1526 PCI_LIB_ADDRESS (
1527 0,
1528 1,
1529 1,
1530 (Atapi->PrimarySecondary == 1) ? 0x42 : 0x40
1531 ),
1532 BIT15
1533 );
1534 }
1535
1536 //
1537 // Next device path node
1538 //
1539 DevPathNode = NextDevicePathNode (DevPathNode);
1540 }
1541 }
1542
1543 return;
1544 }
1545
1546 VOID
1547 InstallDevicePathCallback (
1548 VOID
1549 )
1550 {
1551 DEBUG ((DEBUG_INFO, "Registered NotifyDevPath Event\n"));
1552 mEfiDevPathEvent = EfiCreateProtocolNotifyEvent (
1553 &gEfiDevicePathProtocolGuid,
1554 TPL_CALLBACK,
1555 NotifyDevPath,
1556 NULL,
1557 &mEfiDevPathNotifyReg
1558 );
1559 }
1560
1561 /**
1562 This function is called each second during the boot manager waits the
1563 timeout.
1564
1565 @param TimeoutRemain The remaining timeout.
1566 **/
1567 VOID
1568 EFIAPI
1569 PlatformBootManagerWaitCallback (
1570 UINT16 TimeoutRemain
1571 )
1572 {
1573 //
1574 // Since the timeout should be forced to zero we should never
1575 // Get here
1576 //
1577 ASSERT (FALSE);
1578 }
1579
1580 /**
1581 The function is called when no boot option could be launched,
1582 including platform recovery options and options pointing to applications
1583 built into firmware volumes.
1584
1585 If this function returns, BDS attempts to enter an infinite loop.
1586 **/
1587 VOID
1588 EFIAPI
1589 PlatformBootManagerUnableToBoot (
1590 VOID
1591 )
1592 {
1593 //
1594 // If we get here something failed about the grub boot but since
1595 // We're privy to the secret we must panic and not retry or loop
1596 //
1597 ASSERT (FALSE);
1598 CpuDeadLoop ();
1599 }