1 /** @file
2   This file include all platform action which can be customized by IBV/OEM.
3 
4 Copyright (c) 2017 - 2019, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
6 
7 **/
8 
9 #include "BdsPlatform.h"
10 #include <Guid/EventGroup.h>
11 #include <Protocol/DxeSmmReadyToLock.h>
12 #include <Protocol/FirmwareVolume2.h>
13 #include <Protocol/PciRootBridgeIo.h>
14 
15 #include <Protocol/BlockIo.h>
16 #include <Protocol/PciIo.h>
17 #include <Library/IoLib.h>
18 #include <Library/PciLib.h>
19 #include <Guid/EventGroup.h>
20 
21 #include <Library/Tcg2PhysicalPresenceLib.h>
22 
23 #include <Library/HobLib.h>
24 #include <Protocol/UsbIo.h>
25 #include <Library/BootLogoLib.h>
26 
27 #include <Library/UefiBootManagerLib.h>
28 
29 GLOBAL_REMOVE_IF_UNREFERENCED EFI_BOOT_MODE                 gBootMode;
30 
31 BOOLEAN                      gPPRequireUIConfirm;
32 
33 extern UINTN                                      mBootMenuOptionNumber;
34 
35 GLOBAL_REMOVE_IF_UNREFERENCED USB_CLASS_FORMAT_DEVICE_PATH gUsbClassKeyboardDevicePath = {
36   {
37     {
38       MESSAGING_DEVICE_PATH,
39       MSG_USB_CLASS_DP,
40       {
41         (UINT8) (sizeof (USB_CLASS_DEVICE_PATH)),
42         (UINT8) ((sizeof (USB_CLASS_DEVICE_PATH)) >> 8)
43       }
44     },
45     0xffff,           // VendorId
46     0xffff,           // ProductId
47     CLASS_HID,        // DeviceClass
48     SUBCLASS_BOOT,    // DeviceSubClass
49     PROTOCOL_KEYBOARD // DeviceProtocol
50   },
51   gEndEntire
52 };
53 
54 //
55 // Platform specific ISA serial device path
56 //
57 GLOBAL_REMOVE_IF_UNREFERENCED PLATFORM_ISA_SERIAL_DEVICE_PATH gIsaSerialDevicePath = {
58   gPciRootBridge,
59   gPciIsaBridge,
60   gPnp16550ComPort,
61   gUart(115200, 8, 1, 1),
62   gPcAnsiTerminal,
63   gEndEntire
64 };
65 
66 //
67 // Internal shell mode
68 //
69 GLOBAL_REMOVE_IF_UNREFERENCED UINT32         mShellModeColumn;
70 GLOBAL_REMOVE_IF_UNREFERENCED UINT32         mShellModeRow;
71 GLOBAL_REMOVE_IF_UNREFERENCED UINT32         mShellHorizontalResolution;
72 GLOBAL_REMOVE_IF_UNREFERENCED UINT32         mShellVerticalResolution;
73 //
74 // BDS Platform Functions
75 //
76 
77 BOOLEAN
IsMorBitSet(VOID)78 IsMorBitSet (
79   VOID
80   )
81 {
82   UINTN                     MorControl;
83   EFI_STATUS                Status;
84   UINTN                     DataSize;
85 
86   //
87   // Check if the MOR bit is set.
88   //
89   DataSize = sizeof (MorControl);
90   Status = gRT->GetVariable (
91                   MEMORY_OVERWRITE_REQUEST_VARIABLE_NAME,
92                   &gEfiMemoryOverwriteControlDataGuid,
93                   NULL,
94                   &DataSize,
95                   &MorControl
96                   );
97   if (EFI_ERROR (Status)) {
98     DEBUG ((DEBUG_INFO, " PlatformBootMangerLib: gEfiMemoryOverwriteControlDataGuid doesn't exist!!***\n"));
99     MorControl = 0;
100   } else {
101     DEBUG ((DEBUG_INFO, " PlatformBootMangerLib: Get the gEfiMemoryOverwriteControlDataGuid = %x!!***\n", MorControl));
102   }
103 
104   return (BOOLEAN) (MorControl & 0x01);
105 }
106 
107 VOID
DumpDevicePath(IN CHAR16 * Name,IN EFI_DEVICE_PATH * DevicePath)108 DumpDevicePath (
109   IN CHAR16           *Name,
110   IN EFI_DEVICE_PATH  *DevicePath
111   )
112 {
113   CHAR16 *Str;
114 
115   Str = ConvertDevicePathToText(DevicePath, TRUE, TRUE);
116   DEBUG ((DEBUG_INFO, "%s: %s\n", Name, Str));
117   if (Str != NULL) {
118     FreePool (Str);
119   }
120 }
121 
122 /**
123   An empty function to pass error checking of CreateEventEx ().
124 
125   This empty function ensures that EVT_NOTIFY_SIGNAL_ALL is error
126   checked correctly since it is now mapped into CreateEventEx() in UEFI 2.0.
127 
128   @param  Event                 Event whose notification function is being invoked.
129   @param  Context               The pointer to the notification function's context,
130                                 which is implementation-dependent.
131 **/
132 VOID
133 EFIAPI
InternalBdsEmptyCallbackFuntion(IN EFI_EVENT Event,IN VOID * Context)134 InternalBdsEmptyCallbackFuntion (
135   IN EFI_EVENT                Event,
136   IN VOID                     *Context
137   )
138 {
139   return;
140 }
141 
142 VOID
ExitPmAuth(VOID)143 ExitPmAuth (
144   VOID
145   )
146 {
147   EFI_HANDLE                 Handle;
148   EFI_STATUS                 Status;
149   EFI_EVENT                  EndOfDxeEvent;
150 
151   DEBUG((DEBUG_INFO,"ExitPmAuth ()- Start\n"));
152   //
153   // Prepare S3 information, this MUST be done before ExitPmAuth/EndOfDxe
154   //
155   //
156   // Since PI1.2.1, we need signal EndOfDxe as ExitPmAuth
157   //
158   Status = gBS->CreateEventEx (
159                   EVT_NOTIFY_SIGNAL,
160                   TPL_CALLBACK,
161                   InternalBdsEmptyCallbackFuntion,
162                   NULL,
163                   &gEfiEndOfDxeEventGroupGuid,
164                   &EndOfDxeEvent
165                   );
166   ASSERT_EFI_ERROR (Status);
167   gBS->SignalEvent (EndOfDxeEvent);
168   gBS->CloseEvent (EndOfDxeEvent);
169   DEBUG((DEBUG_INFO,"All EndOfDxe callbacks have returned successfully\n"));
170 
171   //
172   // NOTE: We need install DxeSmmReadyToLock directly here because many boot script is added via ExitPmAuth/EndOfDxe callback.
173   // If we install them at same callback, these boot script will be rejected because BootScript Driver runs first to lock them done.
174   // So we seperate them to be 2 different events, ExitPmAuth is last chance to let platform add boot script. DxeSmmReadyToLock will
175   // make boot script save driver lock down the interface.
176   //
177   Handle = NULL;
178   Status = gBS->InstallProtocolInterface (
179                   &Handle,
180                   &gEfiDxeSmmReadyToLockProtocolGuid,
181                   EFI_NATIVE_INTERFACE,
182                   NULL
183                   );
184   ASSERT_EFI_ERROR (Status);
185   DEBUG((DEBUG_INFO,"ExitPmAuth ()- End\n"));
186 }
187 
188 VOID
ConnectRootBridge(BOOLEAN Recursive)189 ConnectRootBridge (
190   BOOLEAN Recursive
191   )
192 {
193   UINTN                            RootBridgeHandleCount;
194   EFI_HANDLE                       *RootBridgeHandleBuffer;
195   UINTN                            RootBridgeIndex;
196 
197   RootBridgeHandleCount = 0;
198   gBS->LocateHandleBuffer (
199          ByProtocol,
200          &gEfiPciRootBridgeIoProtocolGuid,
201          NULL,
202          &RootBridgeHandleCount,
203          &RootBridgeHandleBuffer
204          );
205   for (RootBridgeIndex = 0; RootBridgeIndex < RootBridgeHandleCount; RootBridgeIndex++) {
206     gBS->ConnectController (RootBridgeHandleBuffer[RootBridgeIndex], NULL, NULL, Recursive);
207   }
208 }
209 
210 
211 /**
212   Return whether the device is trusted console.
213 
214   @param Device  The device to be tested.
215 
216   @retval TRUE   The device can be trusted.
217   @retval FALSE  The device cannot be trusted.
218 **/
219 BOOLEAN
IsTrustedConsole(IN CONSOLE_TYPE ConsoleType,IN EFI_DEVICE_PATH_PROTOCOL * Device)220 IsTrustedConsole (
221   IN CONSOLE_TYPE              ConsoleType,
222   IN EFI_DEVICE_PATH_PROTOCOL  *Device
223   )
224 {
225   VOID                      *TrustedConsoleDevicepath;
226   EFI_DEVICE_PATH_PROTOCOL  *TempDevicePath;
227   EFI_DEVICE_PATH_PROTOCOL  *Instance;
228   UINTN                     Size;
229   EFI_DEVICE_PATH_PROTOCOL  *ConsoleDevice;
230 
231   if (Device == NULL) {
232     return FALSE;
233   }
234 
235   ConsoleDevice = DuplicateDevicePath(Device);
236 
237   TrustedConsoleDevicepath = NULL;
238 
239   switch (ConsoleType) {
240   case ConIn:
241     TrustedConsoleDevicepath = PcdGetPtr (PcdTrustedConsoleInputDevicePath);
242     break;
243   case ConOut:
244     //
245     // Check GOP and remove last node
246     //
247     TempDevicePath = ConsoleDevice;
248     while (!IsDevicePathEndType (TempDevicePath)) {
249       if (DevicePathType (TempDevicePath) == ACPI_DEVICE_PATH &&
250           DevicePathSubType (TempDevicePath) == ACPI_ADR_DP) {
251         SetDevicePathEndNode (TempDevicePath);
252         break;
253       }
254       TempDevicePath = NextDevicePathNode (TempDevicePath);
255     }
256 
257     TrustedConsoleDevicepath = PcdGetPtr (PcdTrustedConsoleOutputDevicePath);
258     break;
259   default:
260     ASSERT(FALSE);
261     break;
262   }
263 
264   TempDevicePath = TrustedConsoleDevicepath;
265   do {
266     Instance = GetNextDevicePathInstance (&TempDevicePath, &Size);
267     if (Instance == NULL) {
268       break;
269     }
270 
271     if (CompareMem (ConsoleDevice, Instance, Size - END_DEVICE_PATH_LENGTH) == 0) {
272       FreePool (Instance);
273       FreePool (ConsoleDevice);
274       return TRUE;
275     }
276 
277     FreePool (Instance);
278   } while (TempDevicePath != NULL);
279 
280   FreePool (ConsoleDevice);
281 
282   return FALSE;
283 }
284 
285 BOOLEAN
IsUsbShortForm(IN EFI_DEVICE_PATH_PROTOCOL * DevicePath)286 IsUsbShortForm (
287   IN EFI_DEVICE_PATH_PROTOCOL  *DevicePath
288   )
289 {
290   if ((DevicePathType (DevicePath) == MESSAGING_DEVICE_PATH) &&
291       ((DevicePathSubType (DevicePath) == MSG_USB_CLASS_DP) || (DevicePathSubType (DevicePath) == MSG_USB_WWID_DP)) ) {
292     return TRUE;
293   }
294 
295   return FALSE;
296 }
297 
298 /**
299   Connect the USB short form device path.
300 
301   @param DevicePath   USB short form device path
302 
303   @retval EFI_SUCCESS           Successfully connected the USB device
304   @retval EFI_NOT_FOUND         Cannot connect the USB device
305   @retval EFI_INVALID_PARAMETER The device path is invalid.
306 **/
307 EFI_STATUS
ConnectUsbShortFormDevicePath(IN EFI_DEVICE_PATH_PROTOCOL * DevicePath)308 ConnectUsbShortFormDevicePath (
309   IN EFI_DEVICE_PATH_PROTOCOL   *DevicePath
310   )
311 {
312   EFI_STATUS                            Status;
313   EFI_HANDLE                            *Handles;
314   UINTN                                 HandleCount;
315   UINTN                                 Index;
316   EFI_PCI_IO_PROTOCOL                   *PciIo;
317   UINT8                                 Class[3];
318   BOOLEAN                               AtLeastOneConnected;
319 
320   //
321   // Check the passed in parameters
322   //
323   if (DevicePath == NULL) {
324     return EFI_INVALID_PARAMETER;
325   }
326 
327   if (!IsUsbShortForm (DevicePath)) {
328     return EFI_INVALID_PARAMETER;
329   }
330 
331   //
332   // Find the usb host controller firstly, then connect with the remaining device path
333   //
334   AtLeastOneConnected = FALSE;
335   Status = gBS->LocateHandleBuffer (
336                   ByProtocol,
337                   &gEfiPciIoProtocolGuid,
338                   NULL,
339                   &HandleCount,
340                   &Handles
341                   );
342   for (Index = 0; Index < HandleCount; Index++) {
343     Status = gBS->HandleProtocol (
344                     Handles[Index],
345                     &gEfiPciIoProtocolGuid,
346                     (VOID **) &PciIo
347                     );
348     if (!EFI_ERROR (Status)) {
349       //
350       // Check whether the Pci device is the wanted usb host controller
351       //
352       Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, 0x09, 3, &Class);
353       if (!EFI_ERROR (Status) &&
354           ((PCI_CLASS_SERIAL == Class[2]) && (PCI_CLASS_SERIAL_USB == Class[1]))
355          ) {
356         Status = gBS->ConnectController (
357                         Handles[Index],
358                         NULL,
359                         DevicePath,
360                         FALSE
361                         );
362         if (!EFI_ERROR(Status)) {
363           AtLeastOneConnected = TRUE;
364         }
365       }
366     }
367   }
368 
369   return AtLeastOneConnected ? EFI_SUCCESS : EFI_NOT_FOUND;
370 }
371 
372 /**
373   Update the ConIn/ConOut variable with ISA Serial device path,if its not already exists in ConIn/ConOut
374 **/
375 VOID
EnumIsaSerial(VOID)376 EnumIsaSerial (
377   VOID
378   )
379 {
380   DEBUG ((DEBUG_INFO, "[EnumIsaSerial]\n"));
381   EfiBootManagerUpdateConsoleVariable (ConIn, (EFI_DEVICE_PATH_PROTOCOL *) &gIsaSerialDevicePath, NULL);
382   EfiBootManagerUpdateConsoleVariable (ConOut, (EFI_DEVICE_PATH_PROTOCOL *) &gIsaSerialDevicePath, NULL);
383 
384   //
385   // Append ISA Serial DevicePath to "ConInDev" and "ConOutDev"
386   //
387   EfiBootManagerUpdateConsoleVariable (ConInDev, (EFI_DEVICE_PATH_PROTOCOL *) &gIsaSerialDevicePath, NULL);
388   EfiBootManagerUpdateConsoleVariable (ConOutDev, (EFI_DEVICE_PATH_PROTOCOL *) &gIsaSerialDevicePath, NULL);
389 }
390 
391 /**
392   Update the ConIn variable with USB Keyboard device path,if its not already exists in ConIn
393 **/
394 VOID
EnumUsbKeyboard(VOID)395 EnumUsbKeyboard (
396   VOID
397   )
398 {
399   DEBUG ((DEBUG_INFO, "[EnumUsbKeyboard]\n"));
400   EfiBootManagerUpdateConsoleVariable (ConIn, (EFI_DEVICE_PATH_PROTOCOL *) &gUsbClassKeyboardDevicePath, NULL);
401 
402   //
403   // Append Usb Keyboard short form DevicePath into "ConInDev"
404   //
405   EfiBootManagerUpdateConsoleVariable (ConInDev, (EFI_DEVICE_PATH_PROTOCOL *) &gUsbClassKeyboardDevicePath, NULL);
406 }
407 
408 BOOLEAN
IsVgaHandle(IN EFI_HANDLE Handle)409 IsVgaHandle (
410   IN EFI_HANDLE Handle
411   )
412 {
413   EFI_PCI_IO_PROTOCOL *PciIo;
414   PCI_TYPE00          Pci;
415   EFI_STATUS          Status;
416 
417   Status = gBS->HandleProtocol (
418                   Handle,
419                   &gEfiPciIoProtocolGuid,
420                   (VOID **)&PciIo
421                   );
422   if (!EFI_ERROR (Status)) {
423     Status = PciIo->Pci.Read (
424                           PciIo,
425                           EfiPciIoWidthUint32,
426                           0,
427                           sizeof (Pci) / sizeof (UINT32),
428                           &Pci
429                           );
430     if (!EFI_ERROR (Status)) {
431       if (IS_PCI_VGA (&Pci) || IS_PCI_OLD_VGA (&Pci)) {
432         return TRUE;
433       }
434     }
435   }
436   return FALSE;
437 }
438 
439 EFI_HANDLE
IsVideoController(IN EFI_DEVICE_PATH_PROTOCOL * DevicePath)440 IsVideoController (
441   IN EFI_DEVICE_PATH_PROTOCOL  *DevicePath
442   )
443 {
444   EFI_DEVICE_PATH_PROTOCOL  *DupDevicePath;
445   EFI_DEVICE_PATH_PROTOCOL  *TempDevicePath;
446   EFI_STATUS                Status;
447   EFI_HANDLE                DeviceHandle;
448 
449   DupDevicePath = DuplicateDevicePath (DevicePath);
450   ASSERT (DupDevicePath != NULL);
451   if (DupDevicePath == NULL) {
452     return NULL;
453   }
454 
455   TempDevicePath = DupDevicePath;
456   Status = gBS->LocateDevicePath (
457                   &gEfiDevicePathProtocolGuid,
458                   &TempDevicePath,
459                   &DeviceHandle
460                   );
461   FreePool (DupDevicePath);
462   if (EFI_ERROR (Status)) {
463     return NULL;
464   }
465 
466   if (IsVgaHandle (DeviceHandle)) {
467     return DeviceHandle;
468   } else {
469     return NULL;
470   }
471 }
472 
473 BOOLEAN
IsGopDevicePath(IN EFI_DEVICE_PATH_PROTOCOL * DevicePath)474 IsGopDevicePath (
475   IN EFI_DEVICE_PATH_PROTOCOL  *DevicePath
476   )
477 {
478   while (!IsDevicePathEndType (DevicePath)) {
479     if (DevicePathType (DevicePath) == ACPI_DEVICE_PATH &&
480         DevicePathSubType (DevicePath) == ACPI_ADR_DP) {
481       return TRUE;
482     }
483     DevicePath = NextDevicePathNode (DevicePath);
484   }
485   return FALSE;
486 }
487 
488 /**
489   Remove all GOP device path instance from DevicePath and add the Gop to the DevicePath.
490 **/
491 EFI_DEVICE_PATH_PROTOCOL *
UpdateGopDevicePath(EFI_DEVICE_PATH_PROTOCOL * DevicePath,EFI_DEVICE_PATH_PROTOCOL * Gop)492 UpdateGopDevicePath (
493   EFI_DEVICE_PATH_PROTOCOL *DevicePath,
494   EFI_DEVICE_PATH_PROTOCOL *Gop
495   )
496 {
497   UINTN                    Size;
498   UINTN                    GopSize;
499   EFI_DEVICE_PATH_PROTOCOL *Temp;
500   EFI_DEVICE_PATH_PROTOCOL *Return;
501   EFI_DEVICE_PATH_PROTOCOL *Instance;
502   BOOLEAN                  Exist;
503 
504   Exist = FALSE;
505   Return = NULL;
506   GopSize = GetDevicePathSize (Gop);
507   do {
508     Instance = GetNextDevicePathInstance (&DevicePath, &Size);
509     if (Instance == NULL) {
510       break;
511     }
512     if (!IsGopDevicePath (Instance) ||
513         (Size == GopSize && CompareMem (Instance, Gop, GopSize) == 0)
514        ) {
515       if (Size == GopSize && CompareMem (Instance, Gop, GopSize) == 0) {
516         Exist = TRUE;
517       }
518       Temp = Return;
519       Return = AppendDevicePathInstance (Return, Instance);
520       if (Temp != NULL) {
521         FreePool (Temp);
522       }
523     }
524     FreePool (Instance);
525   } while (DevicePath != NULL);
526 
527   if (!Exist) {
528     Temp = Return;
529     Return = AppendDevicePathInstance (Return, Gop);
530     if (Temp != NULL) {
531       FreePool (Temp);
532     }
533   }
534   return Return;
535 }
536 
537 /**
538   Get Graphics Controller Handle.
539 
540   @retval GraphicsController    Successfully located
541   @retval NULL                  Failed to locate
542 **/
543 EFI_HANDLE
544 EFIAPI
GetGraphicsController(IN BOOLEAN NeedTrustedConsole)545 GetGraphicsController (
546   IN BOOLEAN    NeedTrustedConsole
547   )
548 {
549   EFI_STATUS                Status;
550   UINTN                     Index;
551   EFI_HANDLE                *PciHandles;
552   UINTN                     PciHandlesSize;
553   EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
554 
555   Status = gBS->LocateHandleBuffer (
556                   ByProtocol,
557                   &gEfiPciIoProtocolGuid,
558                   NULL,
559                   &PciHandlesSize,
560                   &PciHandles
561                   );
562   if (EFI_ERROR (Status)) {
563     return NULL;
564   }
565 
566   for (Index = 0; Index < PciHandlesSize; Index++) {
567     Status = gBS->HandleProtocol (
568                     PciHandles[Index],
569                     &gEfiDevicePathProtocolGuid,
570                     (VOID **) &DevicePath
571                     );
572     if (EFI_ERROR(Status)) {
573       continue;
574     }
575     if (!IsVgaHandle (PciHandles[Index])) {
576       continue;
577     }
578     if ((NeedTrustedConsole && IsTrustedConsole (ConOut, DevicePath)) ||
579         ((!NeedTrustedConsole) && (!IsTrustedConsole (ConOut, DevicePath)))) {
580       return PciHandles[Index];
581     }
582   }
583 
584   return NULL;
585 }
586 
587 VOID
UpdateGraphicConOut(IN BOOLEAN NeedTrustedConsole)588 UpdateGraphicConOut (
589   IN BOOLEAN    NeedTrustedConsole
590   )
591 {
592   EFI_HANDLE                          GraphicsControllerHandle;
593   EFI_DEVICE_PATH_PROTOCOL            *GopDevicePath;
594   EFI_DEVICE_PATH_PROTOCOL            *ConOutDevicePath;
595   EFI_DEVICE_PATH_PROTOCOL            *UpdatedConOutDevicePath;
596 
597   //
598   // Update ConOut variable
599   //
600   GraphicsControllerHandle = GetGraphicsController (NeedTrustedConsole);
601   if (GraphicsControllerHandle != NULL) {
602     //
603     // Connect the GOP driver
604     //
605     gBS->ConnectController (GraphicsControllerHandle, NULL, NULL, TRUE);
606 
607     //
608     // Get the GOP device path
609     // NOTE: We may get a device path that contains Controller node in it.
610     //
611     GopDevicePath = EfiBootManagerGetGopDevicePath (GraphicsControllerHandle);
612     if (GopDevicePath != NULL) {
613       GetEfiGlobalVariable2 (L"ConOut", (VOID **)&ConOutDevicePath, NULL);
614       UpdatedConOutDevicePath = UpdateGopDevicePath (ConOutDevicePath, GopDevicePath);
615       if (ConOutDevicePath != NULL) {
616         FreePool (ConOutDevicePath);
617       }
618       FreePool (GopDevicePath);
619       gRT->SetVariable (
620                       L"ConOut",
621                       &gEfiGlobalVariableGuid,
622                       EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS,
623                       GetDevicePathSize (UpdatedConOutDevicePath),
624                       UpdatedConOutDevicePath
625                       );
626     }
627   }
628 }
629 
630 VOID
AddConsoleVariable(IN CONSOLE_TYPE ConsoleType,IN EFI_DEVICE_PATH * ConsoleDevicePath)631 AddConsoleVariable (
632   IN CONSOLE_TYPE              ConsoleType,
633   IN EFI_DEVICE_PATH           *ConsoleDevicePath
634   )
635 {
636   EFI_DEVICE_PATH           *TempDevicePath;
637   EFI_DEVICE_PATH           *Instance;
638   UINTN                     Size;
639   EFI_HANDLE                GraphicsControllerHandle;
640   EFI_DEVICE_PATH           *GopDevicePath;
641 
642   TempDevicePath = ConsoleDevicePath;
643   do {
644     Instance = GetNextDevicePathInstance (&TempDevicePath, &Size);
645     if (Instance == NULL) {
646       break;
647     }
648 
649     switch (ConsoleType) {
650     case ConIn:
651       if (IsUsbShortForm (Instance)) {
652         //
653         // Append Usb Keyboard short form DevicePath into "ConInDev"
654         //
655         EfiBootManagerUpdateConsoleVariable (ConInDev, Instance, NULL);
656       }
657       EfiBootManagerUpdateConsoleVariable (ConsoleType, Instance, NULL);
658       break;
659     case ConOut:
660       GraphicsControllerHandle = IsVideoController (Instance);
661       if (GraphicsControllerHandle == NULL) {
662         EfiBootManagerUpdateConsoleVariable (ConsoleType, Instance, NULL);
663       } else {
664         //
665         // Connect the GOP driver
666         //
667         gBS->ConnectController (GraphicsControllerHandle, NULL, NULL, TRUE);
668         //
669         // Get the GOP device path
670         // NOTE: We may get a device path that contains Controller node in it.
671         //
672         GopDevicePath = EfiBootManagerGetGopDevicePath (GraphicsControllerHandle);
673         if (GopDevicePath != NULL) {
674           EfiBootManagerUpdateConsoleVariable (ConsoleType, GopDevicePath, NULL);
675         }
676       }
677       break;
678     default:
679       ASSERT(FALSE);
680       break;
681     }
682 
683     FreePool (Instance);
684   } while (TempDevicePath != NULL);
685 }
686 
687 /**
688   The function connects the trusted consoles.
689 **/
690 VOID
ConnectTrustedConsole(VOID)691 ConnectTrustedConsole (
692   VOID
693   )
694 {
695   EFI_DEVICE_PATH_PROTOCOL     *Consoles;
696   EFI_DEVICE_PATH_PROTOCOL     *TempDevicePath;
697   EFI_DEVICE_PATH_PROTOCOL     *Instance;
698   EFI_DEVICE_PATH_PROTOCOL     *Next;
699   UINTN                        Size;
700   UINTN                        Index;
701   EFI_HANDLE                   Handle;
702   EFI_STATUS                   Status;
703   CHAR16                       *ConsoleVar[] = {L"ConIn", L"ConOut"};
704   VOID                         *TrustedConsoleDevicepath;
705 
706   TrustedConsoleDevicepath = PcdGetPtr (PcdTrustedConsoleInputDevicePath);
707   DumpDevicePath (L"TrustedConsoleIn", TrustedConsoleDevicepath);
708   TrustedConsoleDevicepath = PcdGetPtr (PcdTrustedConsoleOutputDevicePath);
709   DumpDevicePath (L"TrustedConsoleOut", TrustedConsoleDevicepath);
710 
711   for (Index = 0; Index < sizeof (ConsoleVar) / sizeof (ConsoleVar[0]); Index++) {
712 
713     GetEfiGlobalVariable2 (ConsoleVar[Index], (VOID **)&Consoles, NULL);
714 
715     TempDevicePath = Consoles;
716     do {
717       Instance = GetNextDevicePathInstance (&TempDevicePath, &Size);
718       if (Instance == NULL) {
719         break;
720       }
721       if (IsTrustedConsole (Index, Instance)) {
722         if (IsUsbShortForm (Instance)) {
723           ConnectUsbShortFormDevicePath (Instance);
724         } else {
725           for (Next = Instance; !IsDevicePathEnd (Next); Next = NextDevicePathNode (Next)) {
726             if (DevicePathType (Next) == ACPI_DEVICE_PATH && DevicePathSubType (Next) == ACPI_ADR_DP) {
727               break;
728             } else if (DevicePathType (Next) == HARDWARE_DEVICE_PATH &&
729                        DevicePathSubType (Next) == HW_CONTROLLER_DP &&
730                        DevicePathType (NextDevicePathNode (Next)) == ACPI_DEVICE_PATH &&
731                        DevicePathSubType (NextDevicePathNode (Next)) == ACPI_ADR_DP
732                        ) {
733               break;
734             }
735           }
736           if (!IsDevicePathEnd (Next)) {
737             SetDevicePathEndNode (Next);
738             Status = EfiBootManagerConnectDevicePath (Instance, &Handle);
739             if (!EFI_ERROR (Status)) {
740               gBS->ConnectController (Handle, NULL, NULL, TRUE);
741             }
742           } else {
743             EfiBootManagerConnectDevicePath (Instance, NULL);
744           }
745         }
746       }
747       FreePool (Instance);
748     } while (TempDevicePath != NULL);
749 
750     if (Consoles != NULL) {
751       FreePool (Consoles);
752     }
753   }
754 }
755 
756 /**
757   The function connects the trusted Storages.
758 **/
759 VOID
ConnectTrustedStorage(VOID)760 ConnectTrustedStorage (
761   VOID
762   )
763 {
764   VOID                      *TrustedStorageDevicepath;
765   EFI_DEVICE_PATH_PROTOCOL  *TempDevicePath;
766   EFI_DEVICE_PATH_PROTOCOL  *Instance;
767   UINTN                     Size;
768   EFI_DEVICE_PATH_PROTOCOL  *TempStorageDevicePath;
769   EFI_STATUS                Status;
770   EFI_HANDLE                DeviceHandle;
771 
772   TrustedStorageDevicepath = PcdGetPtr (PcdTrustedStorageDevicePath);
773   DumpDevicePath (L"TrustedStorage", TrustedStorageDevicepath);
774 
775   TempDevicePath = TrustedStorageDevicepath;
776   do {
777     Instance = GetNextDevicePathInstance (&TempDevicePath, &Size);
778     if (Instance == NULL) {
779       break;
780     }
781 
782     EfiBootManagerConnectDevicePath (Instance, NULL);
783 
784     TempStorageDevicePath = Instance;
785 
786     Status = gBS->LocateDevicePath (
787                     &gEfiDevicePathProtocolGuid,
788                     &TempStorageDevicePath,
789                     &DeviceHandle
790                     );
791     if (!EFI_ERROR (Status)) {
792       gBS->ConnectController (DeviceHandle, NULL, NULL, FALSE);
793     }
794 
795     FreePool (Instance);
796   } while (TempDevicePath != NULL);
797 }
798 
799 /**
800   The function connects the trusted consoles and then call the PP processing library interface.
801 **/
802 VOID
ProcessTcgPp(VOID)803 ProcessTcgPp (
804   VOID
805   )
806 {
807   gPPRequireUIConfirm |= Tcg2PhysicalPresenceLibNeedUserConfirm();
808 
809   if (gPPRequireUIConfirm) {
810     ConnectTrustedConsole ();
811   }
812 
813   Tcg2PhysicalPresenceLibProcessRequest (NULL);
814 }
815 
816 /**
817   The function connects the trusted storage to perform TPerReset.
818 **/
819 VOID
ProcessTcgMor(VOID)820 ProcessTcgMor (
821   VOID
822   )
823 {
824   if (IsMorBitSet ()) {
825     ConnectTrustedConsole();
826     ConnectTrustedStorage();
827   }
828 }
829 
830 /**
831   Check if current BootCurrent variable is internal shell boot option.
832 
833   @retval  TRUE         BootCurrent is internal shell.
834   @retval  FALSE        BootCurrent is not internal shell.
835 **/
836 BOOLEAN
BootCurrentIsInternalShell(VOID)837 BootCurrentIsInternalShell (
838   VOID
839   )
840 {
841   UINTN                         VarSize;
842   UINT16                        BootCurrent;
843   CHAR16                        BootOptionName[16];
844   UINT8                         *BootOption;
845   UINT8                         *Ptr;
846   BOOLEAN                       Result;
847   EFI_STATUS                    Status;
848   EFI_DEVICE_PATH_PROTOCOL      *TempDevicePath;
849   EFI_DEVICE_PATH_PROTOCOL      *LastDeviceNode;
850   EFI_GUID                      *GuidPoint;
851 
852   BootOption = NULL;
853   Result     = FALSE;
854 
855   //
856   // Get BootCurrent variable
857   //
858   VarSize = sizeof (UINT16);
859   Status = gRT->GetVariable (
860                   L"BootCurrent",
861                   &gEfiGlobalVariableGuid,
862                   NULL,
863                   &VarSize,
864                   &BootCurrent
865                   );
866   if (EFI_ERROR (Status)) {
867     return FALSE;
868   }
869 
870   //
871   // Create boot option Bootxxxx from BootCurrent
872   //
873   UnicodeSPrint (BootOptionName, sizeof(BootOptionName), L"Boot%04X", BootCurrent);
874 
875   GetEfiGlobalVariable2 (BootOptionName, (VOID **) &BootOption, &VarSize);
876   if (BootOption == NULL || VarSize == 0) {
877     return FALSE;
878   }
879 
880   Ptr = BootOption;
881   Ptr += sizeof (UINT32);
882   Ptr += sizeof (UINT16);
883   Ptr += StrSize ((CHAR16 *) Ptr);
884   TempDevicePath = (EFI_DEVICE_PATH_PROTOCOL *) Ptr;
885   LastDeviceNode = TempDevicePath;
886   while (!IsDevicePathEnd (TempDevicePath)) {
887     LastDeviceNode = TempDevicePath;
888     TempDevicePath = NextDevicePathNode (TempDevicePath);
889   }
890   GuidPoint = EfiGetNameGuidFromFwVolDevicePathNode (
891                 (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *) LastDeviceNode
892                 );
893   if ((GuidPoint != NULL) &&
894       ((CompareGuid (GuidPoint, &gUefiShellFileGuid)))
895     ) {
896     //
897     // if this option is internal shell, return TRUE
898     //
899     Result = TRUE;
900   }
901 
902   if (BootOption != NULL) {
903     FreePool (BootOption);
904     BootOption = NULL;
905   }
906 
907   return Result;
908 }
909 
910 /**
911   This function will change video resolution and text mode
912   for internl shell when internal shell is launched.
913 
914   @param   None.
915 
916   @retval  EFI_SUCCESS  Mode is changed successfully.
917   @retval  Others       Mode failed to changed.
918 **/
919 EFI_STATUS
920 EFIAPI
ChangeModeForInternalShell(VOID)921 ChangeModeForInternalShell (
922   VOID
923   )
924 {
925   EFI_GRAPHICS_OUTPUT_PROTOCOL          *GraphicsOutput;
926   EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL       *SimpleTextOut;
927   UINTN                                 SizeOfInfo;
928   EFI_GRAPHICS_OUTPUT_MODE_INFORMATION  *Info;
929   UINT32                                MaxGopMode;
930   UINT32                                MaxTextMode;
931   UINT32                                ModeNumber;
932   UINTN                                 HandleCount;
933   EFI_HANDLE                            *HandleBuffer;
934   EFI_STATUS                            Status;
935   UINTN                                 Index;
936   UINTN                                 CurrentColumn;
937   UINTN                                 CurrentRow;
938 
939   Status = gBS->HandleProtocol (
940                   gST->ConsoleOutHandle,
941                   &gEfiGraphicsOutputProtocolGuid,
942                   (VOID**)&GraphicsOutput
943                   );
944   if (EFI_ERROR (Status)) {
945     GraphicsOutput = NULL;
946   }
947 
948   Status = gBS->HandleProtocol (
949                   gST->ConsoleOutHandle,
950                   &gEfiSimpleTextOutProtocolGuid,
951                   (VOID**)&SimpleTextOut
952                   );
953   if (EFI_ERROR (Status)) {
954     SimpleTextOut = NULL;
955   }
956 
957   if ((GraphicsOutput == NULL) || (SimpleTextOut == NULL)) {
958     return EFI_UNSUPPORTED;
959   }
960 
961   MaxGopMode  = GraphicsOutput->Mode->MaxMode;
962   MaxTextMode = SimpleTextOut->Mode->MaxMode;
963 
964   //
965   // 1. If current video resolution is same with new video resolution,
966   //    video resolution need not be changed.
967   //    1.1. If current text mode is same with new text mode, text mode need not be change.
968   //    1.2. If current text mode is different with new text mode, text mode need be change to new text mode.
969   // 2. If current video resolution is different with new video resolution, we need restart whole console drivers.
970   //
971   for (ModeNumber = 0; ModeNumber < MaxGopMode; ModeNumber++) {
972     Status = GraphicsOutput->QueryMode (
973                        GraphicsOutput,
974                        ModeNumber,
975                        &SizeOfInfo,
976                        &Info
977                        );
978     if (!EFI_ERROR (Status)) {
979       if ((Info->HorizontalResolution == mShellHorizontalResolution) &&
980           (Info->VerticalResolution == mShellVerticalResolution)) {
981         if ((GraphicsOutput->Mode->Info->HorizontalResolution == mShellHorizontalResolution) &&
982             (GraphicsOutput->Mode->Info->VerticalResolution == mShellVerticalResolution)) {
983           //
984           // If current video resolution is same with new resolution,
985           // then check if current text mode is same with new text mode.
986           //
987           Status = SimpleTextOut->QueryMode (SimpleTextOut, SimpleTextOut->Mode->Mode, &CurrentColumn, &CurrentRow);
988           ASSERT_EFI_ERROR (Status);
989           if (CurrentColumn == mShellModeColumn && CurrentRow == mShellModeRow) {
990             //
991             // Current text mode is same with new text mode, text mode need not be change.
992             //
993             FreePool (Info);
994             return EFI_SUCCESS;
995           } else {
996             //
997             // Current text mode is different with new text mode, text mode need be change to new text mode.
998             //
999             for (Index = 0; Index < MaxTextMode; Index++) {
1000               Status = SimpleTextOut->QueryMode (SimpleTextOut, Index, &CurrentColumn, &CurrentRow);
1001               if (!EFI_ERROR(Status)) {
1002                 if ((CurrentColumn == mShellModeColumn) && (CurrentRow == mShellModeRow)) {
1003                   //
1004                   // New text mode is supported, set it.
1005                   //
1006                   Status = SimpleTextOut->SetMode (SimpleTextOut, Index);
1007                   ASSERT_EFI_ERROR (Status);
1008                   //
1009                   // Update text mode PCD.
1010                   //
1011                   Status = PcdSet32S (PcdConOutColumn, mShellModeColumn);
1012                   ASSERT_EFI_ERROR (Status);
1013 
1014                   Status = PcdSet32S (PcdConOutRow, mShellModeRow);
1015                   ASSERT_EFI_ERROR (Status);
1016 
1017                   FreePool (Info);
1018                   return EFI_SUCCESS;
1019                 }
1020               }
1021             }
1022             if (Index == MaxTextMode) {
1023               //
1024               // If new text mode is not supported, return error.
1025               //
1026               FreePool (Info);
1027               return EFI_UNSUPPORTED;
1028             }
1029           }
1030         } else {
1031           FreePool (Info);
1032           //
1033           // If current video resolution is not same with the new one, set new video resolution.
1034           // In this case, the driver which produces simple text out need be restarted.
1035           //
1036           Status = GraphicsOutput->SetMode (GraphicsOutput, ModeNumber);
1037           if (!EFI_ERROR (Status)) {
1038             //
1039             // Set PCD to restart GraphicsConsole and Consplitter to change video resolution
1040             // and produce new text mode based on new resolution.
1041             //
1042             Status = PcdSet32S (PcdVideoHorizontalResolution, mShellHorizontalResolution);
1043             ASSERT_EFI_ERROR (Status);
1044 
1045             Status = PcdSet32S (PcdVideoVerticalResolution, mShellVerticalResolution);
1046             ASSERT_EFI_ERROR (Status);
1047 
1048             Status = PcdSet32S (PcdConOutColumn, mShellModeColumn);
1049             ASSERT_EFI_ERROR (Status);
1050 
1051             Status = PcdSet32S (PcdConOutRow, mShellModeRow);
1052             ASSERT_EFI_ERROR (Status);
1053 
1054             Status = gBS->LocateHandleBuffer (
1055                              ByProtocol,
1056                              &gEfiSimpleTextOutProtocolGuid,
1057                              NULL,
1058                              &HandleCount,
1059                              &HandleBuffer
1060                              );
1061             if (!EFI_ERROR (Status)) {
1062               for (Index = 0; Index < HandleCount; Index++) {
1063                 gBS->DisconnectController (HandleBuffer[Index], NULL, NULL);
1064               }
1065               for (Index = 0; Index < HandleCount; Index++) {
1066                 gBS->ConnectController (HandleBuffer[Index], NULL, NULL, TRUE);
1067               }
1068               if (HandleBuffer != NULL) {
1069                 FreePool (HandleBuffer);
1070               }
1071               break;
1072             }
1073           }
1074         }
1075       }
1076       FreePool (Info);
1077     }
1078   }
1079 
1080   if (ModeNumber == MaxGopMode) {
1081     //
1082     // If the new resolution is not supported, return error.
1083     //
1084     return EFI_UNSUPPORTED;
1085   }
1086 
1087   return EFI_SUCCESS;
1088 }
1089 
1090 /**
1091   ReadyToBoot callback to set video and text mode for internal shell boot.
1092   That will not connect USB controller while CSM and FastBoot are disabled, we need to connect them
1093   before booting to Shell for showing USB devices in Shell.
1094 
1095   When FastBoot is enabled and Windows Console is the chosen Console behavior, input devices will not be connected
1096   by default. Hence, when booting to EFI shell, connecting input consoles are required.
1097 
1098   @param  Event   Pointer to this event
1099   @param  Context Event hanlder private data
1100 
1101   @retval None.
1102 **/
1103 VOID
1104 EFIAPI
OnReadyToBootCallBack(IN EFI_EVENT Event,IN VOID * Context)1105 OnReadyToBootCallBack (
1106   IN  EFI_EVENT                 Event,
1107   IN  VOID                      *Context
1108   )
1109 {
1110   DEBUG ((DEBUG_INFO, "OnReadyToBootCallBack\n"));
1111 
1112   if (BootCurrentIsInternalShell ()) {
1113 
1114     ChangeModeForInternalShell ();
1115     EfiBootManagerConnectAllDefaultConsoles();
1116     gDS->Dispatch ();
1117   }
1118 }
1119 
1120 /**
1121   Platform Bds init. Incude the platform firmware vendor, revision
1122   and so crc check.
1123 **/
1124 VOID
1125 EFIAPI
PlatformBootManagerBeforeConsole(VOID)1126 PlatformBootManagerBeforeConsole (
1127   VOID
1128   )
1129 {
1130   EFI_STATUS                          Status;
1131   EFI_DEVICE_PATH_PROTOCOL            *VarConOut;
1132   EFI_DEVICE_PATH_PROTOCOL            *VarConIn;
1133   EFI_EVENT                           Event;
1134 
1135   DEBUG ((DEBUG_INFO, "PlatformBootManagerBeforeConsole\n"));
1136 
1137   Status = EFI_SUCCESS;
1138 
1139   //
1140   // Get user defined text mode for internal shell only once.
1141   //
1142   mShellHorizontalResolution = PcdGet32 (PcdSetupVideoHorizontalResolution);
1143   mShellVerticalResolution   = PcdGet32 (PcdSetupVideoVerticalResolution);
1144   mShellModeColumn           = PcdGet32 (PcdSetupConOutColumn);
1145   mShellModeRow              = PcdGet32 (PcdSetupConOutRow);
1146 
1147   //
1148   // Create event to set proper video resolution and text mode for internal shell.
1149   //
1150   Status = EfiCreateEventReadyToBootEx (
1151              TPL_CALLBACK,
1152              OnReadyToBootCallBack,
1153              NULL,
1154              &Event
1155              );
1156   ASSERT_EFI_ERROR (Status);
1157 
1158   //
1159   // Connect Root Bridge to make PCI BAR resource allocated and all PciIo created
1160   //
1161   ConnectRootBridge (FALSE);
1162 
1163   //
1164   // Fill ConIn/ConOut in Full Configuration boot mode
1165   //
1166   gBootMode = GetBootModeHob();
1167   DEBUG ((DEBUG_INFO, "PlatformBootManagerBeforeConsole: BootMode = %x\n", gBootMode));
1168 
1169   if (gBootMode == BOOT_WITH_FULL_CONFIGURATION ||
1170       gBootMode == BOOT_WITH_DEFAULT_SETTINGS ||
1171       gBootMode == BOOT_WITH_FULL_CONFIGURATION_PLUS_DIAGNOSTICS ||
1172       gBootMode == BOOT_IN_RECOVERY_MODE) {
1173 
1174     GetEfiGlobalVariable2 (L"ConOut", (VOID **)&VarConOut, NULL);   if (VarConOut != NULL) { FreePool (VarConOut); }
1175     GetEfiGlobalVariable2 (L"ConIn", (VOID **)&VarConIn, NULL);    if (VarConIn  != NULL) { FreePool (VarConIn);  }
1176 
1177     //
1178     // Only fill ConIn/ConOut when ConIn/ConOut is empty because we may drop to Full Configuration boot mode in non-first boot
1179     //
1180     if (VarConOut == NULL || VarConIn == NULL) {
1181       if (PcdGetSize (PcdTrustedConsoleOutputDevicePath) >= sizeof(EFI_DEVICE_PATH_PROTOCOL)) {
1182         AddConsoleVariable (ConOut, PcdGetPtr (PcdTrustedConsoleOutputDevicePath));
1183       }
1184       if (PcdGetSize (PcdTrustedConsoleInputDevicePath) >= sizeof(EFI_DEVICE_PATH_PROTOCOL)) {
1185         AddConsoleVariable (ConIn, PcdGetPtr (PcdTrustedConsoleInputDevicePath));
1186       }
1187     }
1188   }
1189 
1190   EnumIsaSerial ();
1191 
1192   EnumUsbKeyboard ();
1193   //
1194   // For trusted console it must be handled here.
1195   //
1196   UpdateGraphicConOut (TRUE);
1197 
1198   if (gBootMode == BOOT_ON_FLASH_UPDATE) {
1199     //
1200     // Logo show
1201     //
1202     BootLogoEnableLogo ();
1203 
1204     DEBUG((DEBUG_INFO, "ProcessCapsules Before EndOfDxe......\n"));
1205     ProcessCapsules ();
1206     DEBUG((DEBUG_INFO, "ProcessCapsules Done\n"));
1207   }
1208 
1209   //
1210   // Dynamically register hot key: F2/F7/Enter
1211   //
1212   RegisterDefaultBootOption ();
1213   RegisterStaticHotkey ();
1214 
1215   PERF_START_EX(NULL,"EventRec", NULL, AsmReadTsc(), 0x7010);
1216   if (PcdGetBool (PcdTpm2Enable)) {
1217     ProcessTcgPp ();
1218     ProcessTcgMor ();
1219   }
1220   PERF_END_EX(NULL,"EventRec", NULL, AsmReadTsc(), 0x7011);
1221 
1222   //
1223   // We should make all UEFI memory and GCD information populated before ExitPmAuth.
1224   // SMM may consume these information.
1225   //
1226   MemoryTest((EXTENDMEM_COVERAGE_LEVEL) PcdGet32 (PcdPlatformMemoryCheckLevel));
1227 
1228   PERF_START_EX(NULL,"EventRec", NULL, AsmReadTsc(), 0x7020);
1229   ExitPmAuth ();
1230   PERF_END_EX(NULL,"EventRec", NULL, AsmReadTsc(), 0x7021);
1231 
1232   //
1233   // Dispatch the deferred 3rd party images.
1234   //
1235   EfiBootManagerDispatchDeferredImages ();
1236 
1237   //
1238   // For non-trusted console it must be handled here.
1239   //
1240   UpdateGraphicConOut (FALSE);
1241 
1242   if (gBootMode == BOOT_ON_FLASH_UPDATE) {
1243     //
1244     // Logo show
1245     //
1246     BootLogoEnableLogo ();
1247 
1248     DEBUG((DEBUG_INFO, "ProcessCapsules After ConnectAll......\n"));
1249     ProcessCapsules();
1250     DEBUG((DEBUG_INFO, "ProcessCapsules Done\n"));
1251   }
1252 }
1253 
1254 
1255 /**
1256   Connect with predeined platform connect sequence,
1257   the OEM/IBV can customize with their own connect sequence.
1258 
1259   @param[in] BootMode          Boot mode of this boot.
1260 **/
1261 VOID
ConnectSequence(IN EFI_BOOT_MODE BootMode)1262 ConnectSequence (
1263   IN EFI_BOOT_MODE         BootMode
1264   )
1265 {
1266   switch (BootMode) {
1267   case BOOT_ASSUMING_NO_CONFIGURATION_CHANGES:
1268   case BOOT_WITH_MINIMAL_CONFIGURATION:
1269   case BOOT_ON_S4_RESUME:
1270     break;
1271   case BOOT_WITH_FULL_CONFIGURATION:
1272   case BOOT_WITH_FULL_CONFIGURATION_PLUS_DIAGNOSTICS:
1273   case BOOT_WITH_DEFAULT_SETTINGS:
1274   default:
1275     EfiBootManagerConnectAll ();
1276     break;
1277   }
1278 }
1279 
1280 /**
1281   The function is to consider the boot order which is not in our expectation.
1282   In the case that we need to re-sort the boot option.
1283 
1284   @retval  TRUE         Need to sort Boot Option.
1285   @retval  FALSE        Don't need to sort Boot Option.
1286 **/
1287 BOOLEAN
IsNeedSortBootOption(VOID)1288 IsNeedSortBootOption (
1289   VOID
1290   )
1291 {
1292   EFI_BOOT_MANAGER_LOAD_OPTION  *BootOptions;
1293   UINTN                         BootOptionCount;
1294 
1295   BootOptions = EfiBootManagerGetLoadOptions (&BootOptionCount, LoadOptionTypeBoot);
1296 
1297   //
1298   // If setup is the first priority in boot option, we need to sort boot option.
1299   //
1300   if ((BootOptionCount > 1) &&
1301       (((StrnCmp (BootOptions->Description, L"Enter Setup", StrLen (L"Enter Setup"))) == 0) ||
1302        ((StrnCmp (BootOptions->Description, L"Boot Device List", StrLen (L"Boot Device List"))) == 0))) {
1303     return TRUE;
1304   }
1305 
1306   return FALSE;
1307 }
1308 
1309 /**
1310   The function will excute with as the platform policy, current policy
1311   is driven by boot mode. IBV/OEM can customize this code for their specific
1312   policy action.
1313 
1314   @param DriverOptionList - The header of the driver option link list
1315   @param BootOptionList   - The header of the boot option link list
1316   @param ProcessCapsules  - A pointer to ProcessCapsules()
1317   @param BaseMemoryTest   - A pointer to BaseMemoryTest()
1318 **/
1319 VOID
1320 EFIAPI
PlatformBootManagerAfterConsole(VOID)1321 PlatformBootManagerAfterConsole (
1322   VOID
1323   )
1324 {
1325   EFI_STATUS                    Status;
1326   EFI_BOOT_MODE                 LocalBootMode;
1327 
1328   DEBUG ((DEBUG_INFO, "PlatformBootManagerAfterConsole\n"));
1329 
1330   //
1331   // Get current Boot Mode
1332   //
1333   LocalBootMode = gBootMode;
1334   DEBUG ((DEBUG_INFO, "PlatformBootManagerAfterConsole: BootMode = %x\n", gBootMode));
1335 
1336   //
1337   // Logo show
1338   //
1339   BootLogoEnableLogo ();
1340 
1341   //
1342   // Go the different platform policy with different boot mode
1343   // Notes: this part code can be change with the table policy
1344   //
1345   switch (LocalBootMode) {
1346 
1347 
1348   case BOOT_ASSUMING_NO_CONFIGURATION_CHANGES:
1349   case BOOT_WITH_MINIMAL_CONFIGURATION:
1350   case BOOT_ON_S4_RESUME:
1351     //
1352     // Perform some platform specific connect sequence
1353     //
1354     PERF_START_EX(NULL,"EventRec", NULL, AsmReadTsc(), 0x7050);
1355     ConnectSequence (LocalBootMode);
1356     PERF_END_EX(NULL,"EventRec", NULL, AsmReadTsc(), 0x7051);
1357 
1358     break;
1359 
1360   case BOOT_WITH_FULL_CONFIGURATION:
1361   case BOOT_WITH_FULL_CONFIGURATION_PLUS_DIAGNOSTICS:
1362   case BOOT_WITH_DEFAULT_SETTINGS:
1363   default:
1364     //
1365     // Perform some platform specific connect sequence
1366     //
1367     ConnectSequence (LocalBootMode);
1368 
1369     //
1370     // Only in Full Configuration boot mode we do the enumeration of boot device
1371     //
1372     //
1373     // Dispatch all but Storage Oprom explicitly, because we assume Int13Thunk driver is there.
1374     //
1375     EfiBootManagerRefreshAllBootOption ();
1376 
1377     //
1378     // PXE boot option may appear after boot option enumeration
1379     //
1380 
1381     break;
1382   }
1383 
1384   //
1385   // Use a DynamicHii type pcd to save the boot status, which is used to
1386   // control configuration mode, such as FULL/MINIMAL/NO_CHANGES configuration.
1387   //
1388   DEBUG ((DEBUG_INFO, "PcdBootState = %d\n", PcdGetBool(PcdBootState)));
1389   if (PcdGetBool(PcdBootState)) {
1390     Status = PcdSetBoolS(PcdBootState, FALSE);
1391     if (EFI_ERROR (Status)) {
1392       DEBUG ((DEBUG_ERROR, "Set PcdBootState to FALSE failed.\n"));
1393     }
1394     DEBUG ((DEBUG_INFO, "PcdBootState = %d\n", PcdGetBool(PcdBootState)));
1395   }
1396 
1397   Print (L"Press F7 for BootMenu!\n");
1398 
1399   EfiBootManagerRefreshAllBootOption ();
1400   if (IsNeedSortBootOption()) {
1401     EfiBootManagerSortLoadOptionVariable (LoadOptionTypeBoot, CompareBootOption);
1402   }
1403 }
1404 
1405 /**
1406   The function is called when no boot option could be launched,
1407   including platform recovery options and options pointing to applications
1408   built into firmware volumes.
1409 
1410   If this function returns, BDS attempts to enter an infinite loop.
1411 **/
1412 VOID
1413 EFIAPI
PlatformBootManagerUnableToBoot(VOID)1414 PlatformBootManagerUnableToBoot (
1415   VOID
1416   )
1417 {
1418   EFI_STATUS                   Status;
1419   EFI_BOOT_MANAGER_LOAD_OPTION BootDeviceList;
1420   CHAR16                       OptionName[sizeof ("Boot####")];
1421 
1422   if (mBootMenuOptionNumber == LoadOptionNumberUnassigned) {
1423     return;
1424   }
1425   UnicodeSPrint (OptionName, sizeof (OptionName), L"Boot%04x", mBootMenuOptionNumber);
1426   Status = EfiBootManagerVariableToLoadOption (OptionName, &BootDeviceList);
1427   if (EFI_ERROR (Status)) {
1428     return;
1429   }
1430   for (;;) {
1431     EfiBootManagerBoot (&BootDeviceList);
1432   }
1433 }
1434