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