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