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