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