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