1 /** @file
2 
3   Copyright (c) 2004  - 2015, Intel Corporation. All rights reserved.<BR>
4 
5 
6   This program and the accompanying materials are licensed and made available under
7 
8   the terms and conditions of the BSD License that accompanies this distribution.
9 
10   The full text of the license may be found at
11 
12   http://opensource.org/licenses/bsd-license.php.
13 
14 
15 
16   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
17 
18   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
19 
20 
21 
22 
23 
24 Module Name:
25 
26   BdsPlatform.c
27 
28 Abstract:
29 
30   This file include all platform action which can be customized
31   by IBV/OEM.
32 
33 --*/
34 
35 #include "BdsPlatform.h"
36 #include "SetupMode.h"
37 #include <Guid/SetupVariable.h>
38 #include <Library/TcgPhysicalPresenceLib.h>
39 #include <Library/TrEEPhysicalPresenceLib.h>
40 #include <Protocol/I2cMasterMcg.h>
41 #include <TianoApi.h>
42 #include <PlatformBaseAddresses.h>
43 #include <Protocol/GlobalNvsArea.h>
44 #include <Library/DxeServicesTableLib.h>
45 #include <Protocol/BlockIo.h>
46 #include <PchRegs/PchRegsPcu.h>
47 #include <Library/S3BootScriptLib.h>
48 #include "PchAccess.h"
49 #include "PchRegs/PchRegsSata.h"
50 #include <Library/SerialPortLib.h>
51 #include <Library/DebugLib.h>
52 
53 #include <Library/GenericBdsLib/InternalBdsLib.h>
54 #include <Library/GenericBdsLib/String.h>
55 #include <Library/NetLib.h>
56 
57 EFI_GUID *ConnectDriverTable[] = {
58   &gEfiMmioDeviceProtocolGuid,
59   &gEfiI2cMasterProtocolGuid,
60   &gEfiI2cHostProtocolGuid
61 };
62 
63 #define SHELL_ENVIRONMENT_INTERFACE_PROTOCOL \
64   { \
65     0x47c7b221, 0xc42a, 0x11d2, 0x8e, 0x57, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b \
66   }
67 VOID               *mShellImageCallbackReg = NULL;
68 
69 
70 
71 EFI_USER_PROFILE_HANDLE                           mCurrentUser = NULL;
72 EFI_EVENT                                         mHotKeyTimerEvent = NULL;
73 EFI_EVENT                                         mHitHotkeyEvent = NULL;
74 EFI_EVENT                                         mUsbKeyboardConnectEvent = NULL;
75 BOOLEAN                                           mHotKeyPressed = FALSE;
76 VOID                                              *mHitHotkeyRegistration;
77 #define KEYBOARD_TIMER_INTERVAL                   20000 // 0.02s
78 
79 VOID
80 ConnectUSBController (
81   VOID
82   );
83 
84 EFI_STATUS
85 PlatformBdsConnectSimpleConsole (
86   IN BDS_CONSOLE_CONNECT_ENTRY   *PlatformConsole
87 );
88 
89 VOID
90 BootIntoFirmwareInterface(
91   VOID
92   );
DisableAhciCtlr(IN EFI_EVENT Event,IN VOID * Context)93 
94 VOID
95 EFIAPI
96 PlatformBdsInitHotKeyEvent (
97   VOID
98   );
99 
100 VOID
101 EFIAPI
102 DisableAhciCtlr (
103   IN EFI_EVENT                          Event,
104   IN VOID                               *Context
105   )
106 {
107   UINT32                    PmcDisableAddress;
108   UINT8                     SataStorageAmount;
109   UINT32                    SataBase;
110   UINT16                    SataPortStatus;
111 
112 
113   DEBUG ((EFI_D_INFO, "Disable AHCI event is signalled\n"));
114   SataStorageAmount = 0;
115   SataBase = *(UINT32*) Context;
116 
117   //
118   // BayTrail-M EDS chapter 16 ---- PCI IO Register Offset 92 (SATA Port Control and Status)
119   //
120   SataPortStatus = MmioRead16 (SataBase + R_PCH_SATA_PCS);
121 
122   //
123   // Bit 8 EN: Port 0 Present
124   //
125   if ((SataPortStatus & 0x100) == 0x100) {
126     SataStorageAmount++;
127   }
128 
129   //
130   // Bit 9 EN: Port 1 Present
131   //
132   if ((SataPortStatus & 0x200) == 0x200) {
133     SataStorageAmount++;
134   }
135 
136   //
137   // Disable SATA controller when it sets to AHCI mode without carrying any devices
138   // in order to prevent AHCI yellow bang under Win device manager.
139   //
140   if (SataStorageAmount == 0) {
141     PmcDisableAddress = (MmioRead32 ((PCH_PCI_EXPRESS_BASE_ADDRESS + (UINT32) (31 << 15)) + R_PCH_LPC_PMC_BASE) & B_PCH_LPC_PMC_BASE_BAR) + R_PCH_PMC_FUNC_DIS;
142     MmioOr32 (PmcDisableAddress, B_PCH_PMC_FUNC_DIS_SATA);
143     S3BootScriptSaveMemWrite (
InstallReadyToLock(VOID)144       EfiBootScriptWidthUint32,
145       (UINTN) PmcDisableAddress,
146       1,
147       (VOID *) (UINTN) PmcDisableAddress
148       );
149   }
150 }
151 
152 VOID
153 InstallReadyToLock (
154   VOID
155   )
156 {
157   EFI_STATUS                Status;
158   EFI_HANDLE                Handle;
159   EFI_SMM_ACCESS2_PROTOCOL  *SmmAccess;
160   EFI_ACPI_S3_SAVE_PROTOCOL *AcpiS3Save;
161 
162   //
163   // Install DxeSmmReadyToLock protocol prior to the processing of boot options
164   //
165   Status = gBS->LocateProtocol (
166                   &gEfiSmmAccess2ProtocolGuid,
167                   NULL,
168                   (VOID **) &SmmAccess
169                   );
170   if (!EFI_ERROR (Status)) {
171 
172     //
173     // Prepare S3 information, this MUST be done before DxeSmmReadyToLock
174     //
175     Status = gBS->LocateProtocol (
176                     &gEfiAcpiS3SaveProtocolGuid,
177                     NULL,
178                     (VOID **)&AcpiS3Save
179                     );
180     if (!EFI_ERROR (Status)) {
181       AcpiS3Save->S3Save (AcpiS3Save, NULL);
182     }
183 
184     Handle = NULL;
185     Status = gBS->InstallProtocolInterface (
186                     &Handle,
187                     &gExitPmAuthProtocolGuid,
188                     EFI_NATIVE_INTERFACE,
189                     NULL
190                     );
191     ASSERT_EFI_ERROR (Status);
192 
193     Handle = NULL;
194     Status = gBS->InstallProtocolInterface (
195                     &Handle,
196                     &gEfiDxeSmmReadyToLockProtocolGuid,
197                     EFI_NATIVE_INTERFACE,
198                     NULL
ShellImageCallback(IN EFI_EVENT Event,IN VOID * Context)199                     );
200     ASSERT_EFI_ERROR (Status);
201   }
202 
203   return ;
204 }
205 
206 VOID
207 EFIAPI
208 ShellImageCallback (
209   IN EFI_EVENT                          Event,
210   IN VOID                               *Context
211   )
212 {
213  BdsSetConsoleMode (TRUE);
214  DEBUG ((EFI_D_INFO, "BdsEntry ShellImageCallback \n"));
215 }
216 
217 //
218 // BDS Platform Functions
219 //
220 /**
221   Platform Bds init. Incude the platform firmware vendor, revision
PlatformBdsInit(VOID)222   and so crc check.
223 
224   @param VOID
225 
226   @retval  None.
227 
228 **/
229 VOID
230 EFIAPI
231 PlatformBdsInit (
232   VOID
233   )
234 {
235   EFI_STATUS  Status;
236   EFI_EVENT   ShellImageEvent;
237   EFI_GUID    ShellEnvProtocol = SHELL_ENVIRONMENT_INTERFACE_PROTOCOL;
238 
239   #ifdef __GNUC__
240   SerialPortWrite((UINT8 *)">>>>BdsEntry[GCC]\r\n", 19);
241   #else
242   SerialPortWrite((UINT8 *)">>>>BdsEntry\r\n", 14);
243   #endif
244   BdsLibSaveMemoryTypeInformation ();
245 
246   //
247   // Before user authentication, the user identification devices need be connected
248   // from the platform customized device paths
249   //
250   PlatformBdsConnectAuthDevice ();
251 
252   //
253   // As console is not ready, the auto logon user will be identified.
254   //
255   BdsLibUserIdentify (&mCurrentUser);
256 
257   //
258   // Change Gop mode when boot into Shell
259   //
260   if (mShellImageCallbackReg == NULL) {
261     Status = gBS->CreateEvent (
262                     EFI_EVENT_NOTIFY_SIGNAL,
263                     EFI_TPL_CALLBACK,
264                     ShellImageCallback,
265                     NULL,
266                     &ShellImageEvent
267                     );
268     if (!EFI_ERROR (Status)) {
269       Status = gBS->RegisterProtocolNotify (
270                       &ShellEnvProtocol,
271                       ShellImageEvent,
272                       &mShellImageCallbackReg
273                       );
274 
275       DEBUG ((EFI_D_INFO, "BdsEntry ShellImageCallback \n"));
276     }
277   }
278 }
279 
280 EFI_STATUS
281 GetGopDevicePath (
282    IN  EFI_DEVICE_PATH_PROTOCOL *PciDevicePath,
283    OUT EFI_DEVICE_PATH_PROTOCOL **GopDevicePath
284    )
285 {
286   UINTN                           Index;
287   EFI_STATUS                      Status;
288   EFI_HANDLE                      PciDeviceHandle;
289   EFI_DEVICE_PATH_PROTOCOL        *TempDevicePath;
290   EFI_DEVICE_PATH_PROTOCOL        *TempPciDevicePath;
291   UINTN                           GopHandleCount;
292   EFI_HANDLE                      *GopHandleBuffer;
293 
294   UINTN                                 VarSize;
295   SYSTEM_CONFIGURATION  mSystemConfiguration;
296 
297   if (PciDevicePath == NULL || GopDevicePath == NULL) {
298     return EFI_INVALID_PARAMETER;
299   }
300 
301   //
302   // Initialize the GopDevicePath to be PciDevicePath
303   //
304   *GopDevicePath    = PciDevicePath;
305   TempPciDevicePath = PciDevicePath;
306 
307   Status = gBS->LocateDevicePath (
308                   &gEfiDevicePathProtocolGuid,
309                   &TempPciDevicePath,
310                   &PciDeviceHandle
311                   );
312   if (EFI_ERROR (Status)) {
313     return Status;
314   }
315 
316   //
317   // Try to connect this handle, so that GOP dirver could start on this
318   // device and create child handles with GraphicsOutput Protocol installed
319   // on them, then we get device paths of these child handles and select
320   // them as possible console device.
321   //
322 
323   //
324   // Select display devices
325   //
326   VarSize = sizeof(SYSTEM_CONFIGURATION);
327   Status = gRT->GetVariable(
328                   L"Setup",
329                   &gEfiNormalSetupGuid,
330                   NULL,
331                   &VarSize,
332                   &mSystemConfiguration
333                   );
334   if (EFI_ERROR (Status) || VarSize != sizeof(SYSTEM_CONFIGURATION)) {
335     //The setup variable is corrupted
336     VarSize = sizeof(SYSTEM_CONFIGURATION);
337     Status = gRT->GetVariable(
338               L"SetupRecovery",
339               &gEfiNormalSetupGuid,
340               NULL,
341               &VarSize,
342               &mSystemConfiguration
343               );
344     ASSERT_EFI_ERROR (Status);
345   }
346 
347   if(mSystemConfiguration.BootDisplayDevice != 0x0)
348   {
349     ACPI_ADR_DEVICE_PATH         AcpiAdr;
350     EFI_DEVICE_PATH_PROTOCOL  *MyDevicePath = NULL;
351 
352     AcpiAdr.Header.Type     = ACPI_DEVICE_PATH;
353     AcpiAdr.Header.SubType  = ACPI_ADR_DP;
354 
355     switch (mSystemConfiguration.BootDisplayDevice) {
356     case 1:
357       AcpiAdr.ADR= ACPI_DISPLAY_ADR (1, 0, 0, 1, 0, ACPI_ADR_DISPLAY_TYPE_VGA, PORT_CRT, 0);    //CRT Device
358       break;
359     case 2:
360       AcpiAdr.ADR= ACPI_DISPLAY_ADR (1, 0, 0, 1, 0, ACPI_ADR_DISPLAY_TYPE_EXTERNAL_DIGITAL, PORT_B_HDMI, 0);  //HDMI Device Port B
361       break;
362     case 3:
363       AcpiAdr.ADR= ACPI_DISPLAY_ADR (1, 0, 0, 1, 0, ACPI_ADR_DISPLAY_TYPE_EXTERNAL_DIGITAL, PORT_B_DP, 0);    //DP PortB
364       break;
365     case 4:
366       AcpiAdr.ADR= ACPI_DISPLAY_ADR (1, 0, 0, 1, 0, ACPI_ADR_DISPLAY_TYPE_EXTERNAL_DIGITAL, PORT_C_DP, 0);    //DP PortC
367       break;
368     case 5:
369       AcpiAdr.ADR= ACPI_DISPLAY_ADR (1, 0, 0, 1, 0, ACPI_ADR_DISPLAY_TYPE_INTERNAL_DIGITAL, PORT_C_DP, 0);    //eDP Port C
370       break;
371     case 6:
372       AcpiAdr.ADR= ACPI_DISPLAY_ADR (1, 0, 0, 1, 0, ACPI_ADR_DISPLAY_TYPE_INTERNAL_DIGITAL, PORT_MIPI_A, 0);  //DSI Port A
373       break;
374     case 7:
375       AcpiAdr.ADR= ACPI_DISPLAY_ADR (1, 0, 0, 1, 0, ACPI_ADR_DISPLAY_TYPE_INTERNAL_DIGITAL, PORT_MIPI_C, 0);  //DSI Port C
376       break;
377     default:
378       AcpiAdr.ADR= ACPI_DISPLAY_ADR (1, 0, 0, 1, 0, ACPI_ADR_DISPLAY_TYPE_VGA, PORT_CRT, 0);
379       break;
380     }
381 
382     SetDevicePathNodeLength (&AcpiAdr.Header, sizeof (ACPI_ADR_DEVICE_PATH));
383 
384     MyDevicePath = AppendDevicePathNode(MyDevicePath, (EFI_DEVICE_PATH_PROTOCOL*)&AcpiAdr);
385 
386     gBS->ConnectController (
387            PciDeviceHandle,
388            NULL,
389            MyDevicePath,
390            FALSE
391            );
392 
393     FreePool(MyDevicePath);
394   }
395   else
396   {
397     gBS->ConnectController (
398            PciDeviceHandle,
399            NULL,
400            NULL,
401            FALSE
402            );
403   }
404 
405   Status = gBS->LocateHandleBuffer (
406                   ByProtocol,
407                   &gEfiGraphicsOutputProtocolGuid,
408                   NULL,
409                   &GopHandleCount,
410                   &GopHandleBuffer
411                   );
412   if (!EFI_ERROR (Status)) {
413     //
414     // Add all the child handles as possible Console Device
415     //
416     for (Index = 0; Index < GopHandleCount; Index++) {
417       Status = gBS->HandleProtocol (
418                       GopHandleBuffer[Index],
419                       &gEfiDevicePathProtocolGuid,
420                       (VOID**)&TempDevicePath
421                       );
422       if (EFI_ERROR (Status)) {
423         continue;
424       }
425       if (CompareMem (
426             PciDevicePath,
427             TempDevicePath,
428             GetDevicePathSize (PciDevicePath) - END_DEVICE_PATH_LENGTH
429             ) == 0) {
430         //
431         // In current implementation, we only enable one of the child handles
432         // as console device, i.e. sotre one of the child handle's device
433         // path to variable "ConOut"
434         // In futhure, we could select all child handles to be console device
435         //
436         *GopDevicePath = TempDevicePath;
437       }
438     }
439     gBS->FreePool (GopHandleBuffer);
440   }
441 
442   return EFI_SUCCESS;
443 }
444 
445 /**
446 
447   Search out all the platform pci or agp video device. The function may will
448   find multiple video device, and return all enabled device path.
449 
450   @param PlugInPciVgaDevicePath    Return the platform plug in pci video device
451                                    path if the system have plug in pci video device.
452   @param OnboardPciVgaDevicePath   Return the platform active agp video device path
453                                    if the system have plug in agp video device or on
GetPlugInPciVgaDevicePath(IN OUT EFI_DEVICE_PATH_PROTOCOL ** PlugInPciVgaDevicePath,IN OUT EFI_DEVICE_PATH_PROTOCOL ** OnboardPciVgaDevicePath)454                                    chip agp device.
455 
456   @retval EFI_SUCCSS               Get all platform active video device path.
457   @retval EFI_STATUS               Return the status of gBS->LocateDevicePath (),
458                                    gBS->ConnectController (),
459                                    and gBS->LocateHandleBuffer ().
460 
461 **/
462 EFI_STATUS
463 GetPlugInPciVgaDevicePath (
464   IN OUT EFI_DEVICE_PATH_PROTOCOL     **PlugInPciVgaDevicePath,
465   IN OUT EFI_DEVICE_PATH_PROTOCOL     **OnboardPciVgaDevicePath
466   )
467 {
468   EFI_STATUS                Status;
469   EFI_HANDLE                RootHandle;
470   UINTN                     HandleCount;
471   EFI_HANDLE                *HandleBuffer;
472   UINTN                     Index;
473   UINTN                     Index1;
474   EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
475   BOOLEAN                   PlugInPciVga;
476   EFI_PCI_IO_PROTOCOL       *PciIo;
477   PCI_TYPE00                Pci;
478 
479   DevicePath = NULL;
480   PlugInPciVga = TRUE;
481   HandleCount = 0;
482   HandleBuffer = NULL;
483 
484   //
485   // Make all the PCI_IO protocols on PCI Seg 0 show up
486   //
487   BdsLibConnectDevicePath (gPlatformRootBridges[0]);
488 
489   Status = gBS->LocateDevicePath (
490                   &gEfiDevicePathProtocolGuid,
491                   &gPlatformRootBridges[0],
492                   &RootHandle
493                   );
494   if (EFI_ERROR (Status)) {
495     return Status;
496   }
497 
498   Status = gBS->ConnectController (
499                   RootHandle,
500                   NULL,
501                   NULL,
502                   FALSE
503                   );
504   if (EFI_ERROR (Status)) {
505     return Status;
506   }
507 
508   //
509   // Start to check all the pci io to find all possible VGA device
510   //
511   HandleCount = 0;
512   HandleBuffer = NULL;
513   Status = gBS->LocateHandleBuffer (
514                   ByProtocol,
515                   &gEfiPciIoProtocolGuid,
516                   NULL,
517                   &HandleCount,
518                   &HandleBuffer
519                   );
520   if (EFI_ERROR (Status)) {
521     return Status;
522   }
523 
524   for (Index = 0; Index < HandleCount; Index++) {
525     Status = gBS->HandleProtocol (
526                     HandleBuffer[Index],
527                     &gEfiPciIoProtocolGuid,
528                     (VOID**)&PciIo
529                     );
530     if (!EFI_ERROR (Status)) {
531 
532       //
533       // Check for all VGA device
534       //
535       Status = PciIo->Pci.Read (
536                         PciIo,
537                         EfiPciIoWidthUint32,
538                         0,
539                         sizeof (Pci) / sizeof (UINT32),
540                         &Pci
541                         );
542       if (EFI_ERROR (Status)) {
543         continue;
544       }
545 
546       //
547       // Here we decide which VGA device to enable in PCI bus
548       //
549       // The first plugin PCI VGA card device will be present as PCI VGA
550       // The onchip AGP or AGP card will be present as AGP VGA
551       //
552       if (!IS_PCI_VGA (&Pci)) {
553         continue;
554       }
555 
556       //
557       // Set the device as the possible console out device,
558       //
559       // Below code will make every VGA device to be one
560       // of the possibe console out device
561       //
562       PlugInPciVga = TRUE;
563       gBS->HandleProtocol (
564              HandleBuffer[Index],
565              &gEfiDevicePathProtocolGuid,
566              (VOID**)&DevicePath
567              );
568 
569       Index1 = 0;
570 
571       while (gPlatformAllPossiblePciVgaConsole[Index1] != NULL) {
572         if (CompareMem (
573               DevicePath,
574               gPlatformAllPossiblePciVgaConsole[Index1],
575               GetDevicePathSize (gPlatformAllPossiblePciVgaConsole[Index1])
576               ) == 0) {
577 
578           //
579           // This device is an AGP device
580           //
581           *OnboardPciVgaDevicePath = DevicePath;
582           PlugInPciVga = FALSE;
583           break;
584         }
585 
586         Index1 ++;
587       }
588 
589       if (PlugInPciVga) {
590         *PlugInPciVgaDevicePath = DevicePath;
591       }
592     }
593   }
594 
595   FreePool (HandleBuffer);
596 
597   return EFI_SUCCESS;
598 }
599 
600 /**
601 
602   Find the platform  active vga, and base on the policy to enable the vga as
603   the console out device. The policy is driven by one setup variable "VBIOS".
PlatformBdsForceActiveVga(VOID)604 
605   None.
606 
607   @param EFI_UNSUPPORTED         There is no active vga device
608 
609   @retval EFI_STATUS             Return the status of BdsLibGetVariableAndSize ()
610 
611 **/
612 EFI_STATUS
613 PlatformBdsForceActiveVga (
614   VOID
615   )
616 {
617   EFI_STATUS                Status;
618   EFI_DEVICE_PATH_PROTOCOL  *PlugInPciVgaDevicePath;
619   EFI_DEVICE_PATH_PROTOCOL  *OnboardPciVgaDevicePath;
620   EFI_DEVICE_PATH_PROTOCOL  *DevicePathFirst;
621   EFI_DEVICE_PATH_PROTOCOL  *DevicePathSecond;
622   EFI_DEVICE_PATH_PROTOCOL  *GopDevicePath;
623   UINTN                VarSize;
624   SYSTEM_CONFIGURATION  mSystemConfiguration;
625 
626   Status = EFI_SUCCESS;
627   PlugInPciVgaDevicePath = NULL;
628   OnboardPciVgaDevicePath = NULL;
629 
630   //
631   // Check the policy which is the first enabled VGA
632   //
633   GetPlugInPciVgaDevicePath (&PlugInPciVgaDevicePath, &OnboardPciVgaDevicePath);
634 
635   if (PlugInPciVgaDevicePath == NULL && OnboardPciVgaDevicePath == NULL) {
636     return EFI_UNSUPPORTED;
637   }
638 
639   VarSize = sizeof(SYSTEM_CONFIGURATION);
640   Status = gRT->GetVariable(
641                   L"Setup",
642                   &gEfiNormalSetupGuid,
643                   NULL,
644                   &VarSize,
645                   &mSystemConfiguration
646                   );
647   if (EFI_ERROR (Status) || VarSize != sizeof(SYSTEM_CONFIGURATION)) {
648     //The setup variable is corrupted
649     VarSize = sizeof(SYSTEM_CONFIGURATION);
650     Status = gRT->GetVariable(
651               L"SetupRecovery",
652               &gEfiNormalSetupGuid,
653               NULL,
654               &VarSize,
655               &mSystemConfiguration
656               );
657     ASSERT_EFI_ERROR (Status);
658   }
659 
660 
661   if ((PlugInPciVgaDevicePath == NULL && OnboardPciVgaDevicePath != NULL) ) {
662     DEBUG ((EFI_D_ERROR,"Update onboard PCI VGA ...\n"));
663     DevicePathFirst  = OnboardPciVgaDevicePath;
664     DevicePathSecond = PlugInPciVgaDevicePath;
665     goto UpdateConOut;
666   }
667   if(OnboardPciVgaDevicePath != NULL && mSystemConfiguration.PrimaryVideoAdaptor == 0) {
668     DEBUG ((EFI_D_ERROR,"Update onboard PCI VGA When set primary!!!...\n"));
669     DevicePathFirst  = OnboardPciVgaDevicePath;
670     DevicePathSecond = PlugInPciVgaDevicePath;
671     goto UpdateConOut;
672   }
673 
674   DEBUG ((EFI_D_ERROR,"Update plug in PCI VGA ...\n"));
675   DevicePathFirst  = PlugInPciVgaDevicePath;
676   DevicePathSecond = OnboardPciVgaDevicePath;
677 
678 UpdateConOut:
679   GetGopDevicePath (DevicePathFirst, &GopDevicePath);
680   DevicePathFirst = GopDevicePath;
681 
682   Status = BdsLibUpdateConsoleVariable (
683              L"ConOut",
684              DevicePathFirst,
685              DevicePathSecond
686              );
687 
688   return Status;
689 }
690 
691 VOID
692 UpdateConsoleResolution(
693   VOID
694   )
695 {
696   UINT32                 HorizontalResolution;
697   UINT32                 VerticalResolution;
698   SYSTEM_CONFIGURATION   SystemConfiguration;
699   UINTN                  VarSize;
700   EFI_STATUS             Status;
701 
702 
703   HorizontalResolution = PcdGet32 (PcdSetupVideoHorizontalResolution);
704   VerticalResolution = PcdGet32 (PcdSetupVideoVerticalResolution);
705 
706   VarSize = sizeof(SYSTEM_CONFIGURATION);
707   Status = gRT->GetVariable(
708                   L"Setup",
709                   &gEfiNormalSetupGuid,
710                   NULL,
711                   &VarSize,
712                   &SystemConfiguration
713                   );
714   if (EFI_ERROR (Status) || VarSize != sizeof(SYSTEM_CONFIGURATION)) {
715     //The setup variable is corrupted
716     VarSize = sizeof(SYSTEM_CONFIGURATION);
717     Status = gRT->GetVariable(
718               L"SetupRecovery",
719               &gEfiNormalSetupGuid,
720               NULL,
721               &VarSize,
722               &SystemConfiguration
723               );
724     ASSERT_EFI_ERROR (Status);
725   }
726 
727   switch (SystemConfiguration.IgdFlatPanel) {
728 
729   case 0:
730     //
731     // Use the detault PCD values.
732     //
733     break;
734 
735   case 1:
736     HorizontalResolution = 640;
737     VerticalResolution = 480;
738     break;
739 
740   case 2:
741     HorizontalResolution = 800;
742     VerticalResolution = 600;
743     break;
744 
745   case 3:
746     HorizontalResolution = 1024;
747     VerticalResolution = 768;
748     break;
749 
750   case 4:
751   HorizontalResolution = 1280;
752   VerticalResolution = 1024;
753   break;
754 
755   case 5:
756   HorizontalResolution = 1366;
757   VerticalResolution = 768;
758   break;
759 
760   case 6:
761   HorizontalResolution = 1680;
762   VerticalResolution = 1050;
763   break;
764 
765   case 7:
766   HorizontalResolution = 1920;
767   VerticalResolution = 1200;
768   break;
769 
770   case 8:
771   HorizontalResolution = 1280;
772   VerticalResolution = 800;
773   break;
774   }
775 
776   PcdSet32 (PcdSetupVideoHorizontalResolution, HorizontalResolution);
777   PcdSet32 (PcdSetupVideoVerticalResolution, VerticalResolution);
778   DEBUG ((EFI_D_ERROR, "HorizontalResolution = %x; VerticalResolution = %x", HorizontalResolution, VerticalResolution));
779 
780   return;
781 }
782 
783 /**
784   Connect the predefined platform default console device. Always try to find
785   and enable the vga device if have.
786 
787   @param PlatformConsole    Predfined platform default console device array.
788 
PlatformBdsConnectConsole(IN BDS_CONSOLE_CONNECT_ENTRY * PlatformConsole)789   @retval EFI_SUCCESS       Success connect at least one ConIn and ConOut
790                             device, there must have one ConOut device is
791                             active vga device.
792 
793   @retval EFI_STATUS        Return the status of
794                             BdsLibConnectAllDefaultConsoles ()
795 
796 **/
797 EFI_STATUS
798 PlatformBdsConnectConsole (
799   IN BDS_CONSOLE_CONNECT_ENTRY   *PlatformConsole
800 )
801 {
802   EFI_STATUS                         Status;
803   UINTN                              Index;
804   EFI_DEVICE_PATH_PROTOCOL           *VarConout;
805   EFI_DEVICE_PATH_PROTOCOL           *VarConin;
806   UINTN                              DevicePathSize;
807 
808   UpdateConsoleResolution();
809 
810   Index = 0;
811   Status = EFI_SUCCESS;
812   DevicePathSize = 0;
813   VarConout = BdsLibGetVariableAndSize (
814                 L"ConOut",
815                 &gEfiGlobalVariableGuid,
816                 &DevicePathSize
817                 );
818   VarConin = BdsLibGetVariableAndSize (
819                L"ConIn",
820                &gEfiGlobalVariableGuid,
821                &DevicePathSize
822                );
823   if (VarConout == NULL || VarConin == NULL) {
824     //
825     // Have chance to connect the platform default console,
826     // the platform default console is the minimue device group
827     // the platform should support
828     //
829     while (PlatformConsole[Index].DevicePath != NULL) {
830 
831       //
832       // Update the console variable with the connect type
833       //
834       if ((PlatformConsole[Index].ConnectType & CONSOLE_IN) == CONSOLE_IN) {
835         BdsLibUpdateConsoleVariable (L"ConIn", PlatformConsole[Index].DevicePath, NULL);
836       }
837 
838       if ((PlatformConsole[Index].ConnectType & CONSOLE_OUT) == CONSOLE_OUT) {
839         BdsLibUpdateConsoleVariable (L"ConOut", PlatformConsole[Index].DevicePath, NULL);
840       }
841 
842       if ((PlatformConsole[Index].ConnectType & STD_ERROR) == STD_ERROR) {
843         BdsLibUpdateConsoleVariable (L"ErrOut", PlatformConsole[Index].DevicePath, NULL);
844       }
845 
846       Index ++;
847     }
848   }
849 
850   //
851   // Make sure we have at least one active VGA, and have the right
852   // active VGA in console variable
853   //
854   Status = PlatformBdsForceActiveVga ();
855   if (EFI_ERROR (Status)) {
856     return Status;
857   }
858 
859   DEBUG ((EFI_D_INFO, "DISPLAY INIT DONE\n"));
860 
861   //
862   // Connect the all the default console with current console variable
863   //
864   Status = BdsLibConnectAllDefaultConsoles ();
865   if (EFI_ERROR (Status)) {
866     return Status;
867   }
868 
869   return EFI_SUCCESS;
870 }
871 
872 /**
PlatformBdsConnectSequence(VOID)873   Connect with predeined platform connect sequence,
874   the OEM/IBV can customize with their own connect sequence.
875 
876   @param None.
877 
878   @retval None.
879 
880 **/
881 VOID
882 PlatformBdsConnectSequence (
883   VOID
884   )
885 {
886   UINTN                     Index;
887 
888   Index = 0;
889 
890   //
891   // Here we can get the customized platform connect sequence
892   // Notes: we can connect with new variable which record the
893   // last time boots connect device path sequence
894   //
895   while (gPlatformConnectSequence[Index] != NULL) {
896 
897     //
898     // Build the platform boot option
899     //
900     BdsLibConnectDevicePath (gPlatformConnectSequence[Index]);
901     Index ++;
902   }
903 
904   //
905   // Just use the simple policy to connect all devices
906   // There should be no difference between debug tip and release tip, or it will be extremely hard to debug.
907   //
908   // There is case that IdeController driver will write boot script in driver model Start() function. It will be rejected by boot script save.
909   // It is only found when DEBUG disabled, because we are using BdsLibConnectAll() when DEBUG enabled.
910   //
911   // So we use BdsLibConnectAll() here to make sure IdeController.Start() is invoked before InstallReadyToLock().
912   // We may also consider to connect SataController only later if needed.
913   //
914   BdsLibConnectAll ();
915 }
916 
917 /**
918 
PlatformBdsGetDriverOption(IN OUT LIST_ENTRY * BdsDriverLists)919   Load the predefined driver option, OEM/IBV can customize this
920   to load their own drivers
921 
922   @param BdsDriverLists  The header of the driver option link list.
923 
924   @retval None.
925 
926 **/
927 VOID
928 PlatformBdsGetDriverOption (
929   IN OUT LIST_ENTRY                  *BdsDriverLists
930   )
931 {
932   UINTN                              Index;
933 
934   Index = 0;
935 
936   //
937   // Here we can get the customized platform driver option
938   //
939   while (gPlatformDriverOption[Index] != NULL) {
940 
941     //
942     // Build the platform boot option
943     //
944     BdsLibRegisterNewOption (BdsDriverLists, gPlatformDriverOption[Index], NULL, L"DriverOrder");
945     Index ++;
946   }
947 
948 }
949 
950 /**
951   This function is used for some critical time if the the system
952   have no any boot option, and there is no time out for user to add
PlatformBdsPredictBootOption(IN OUT LIST_ENTRY * BdsBootOptionList)953   the new boot option. This can also treat as the platform default
954   boot option.
955 
956   @param BdsBootOptionList   The header of the boot option link list.
957 
958   @retval None.
959 
960 **/
961 VOID
962 PlatformBdsPredictBootOption (
963   IN OUT LIST_ENTRY                  *BdsBootOptionList
964   )
965 {
966   UINTN                              Index;
967 
968   Index = 0;
969 
970   //
971   // Here give chance to get platform boot option data
972   //
973   while (gPlatformBootOption[Index] != NULL) {
974 
975     //
976     // Build the platform boot option
977     //
978     BdsLibRegisterNewOption (BdsBootOptionList, gPlatformBootOption[Index], NULL, L"BootOrder");
979     Index ++;
980   }
981 }
982 
983 /**
984   Perform the platform diagnostic, such like test memory. OEM/IBV also
985   can customize this fuction to support specific platform diagnostic.
PlatformBdsDiagnostics(IN EXTENDMEM_COVERAGE_LEVEL MemoryTestLevel,IN BOOLEAN QuietBoot,IN BASEM_MEMORY_TEST BaseMemoryTest)986 
987   @param MemoryTestLevel   The memory test intensive level
988   @param QuietBoot         Indicate if need to enable the quiet boot
989   @param BaseMemoryTest    A pointer to BdsMemoryTest()
990 
991   @retval  None.
992 
993 **/
994 VOID
995 PlatformBdsDiagnostics (
996   IN EXTENDMEM_COVERAGE_LEVEL    MemoryTestLevel,
997   IN BOOLEAN                     QuietBoot,
998   IN BASEM_MEMORY_TEST           BaseMemoryTest
999   )
1000 {
1001   EFI_STATUS                     Status;
1002 
1003   //
1004   // Here we can decide if we need to show
1005   // the diagnostics screen
1006   // Notes: this quiet boot code should be remove
1007   // from the graphic lib
1008   //
1009   if (QuietBoot) {
1010     EnableQuietBoot (PcdGetPtr(PcdLogoFile));
1011 
1012     //
1013     // Perform system diagnostic
1014     //
1015     Status = BaseMemoryTest (MemoryTestLevel);
1016     if (EFI_ERROR (Status)) {
1017       DisableQuietBoot ();
1018     }
1019 
1020     return;
1021   }
1022 
1023   //
1024   // Perform system diagnostic
1025   //
1026   Status = BaseMemoryTest (MemoryTestLevel);
1027 }
1028 
1029 
1030 /**
1031   For EFI boot option, BDS separate them as six types:
1032   1. Network - The boot option points to the SimpleNetworkProtocol device.
1033                Bds will try to automatically create this type boot option when enumerate.
1034   2. Shell   - The boot option points to internal flash shell.
1035                Bds will try to automatically create this type boot option when enumerate.
1036   3. Removable BlockIo      - The boot option only points to the removable media
1037                               device, like USB flash disk, DVD, Floppy etc.
1038                               These device should contain a *removable* blockIo
1039                               protocol in their device handle.
1040                               Bds will try to automatically create this type boot option
1041                               when enumerate.
1042   4. Fixed BlockIo          - The boot option only points to a Fixed blockIo device,
1043                               like HardDisk.
1044                               These device should contain a *fixed* blockIo
1045                               protocol in their device handle.
1046                               BDS will skip fixed blockIo devices, and NOT
1047                               automatically create boot option for them. But BDS
1048                               will help to delete those fixed blockIo boot option,
1049                               whose description rule conflict with other auto-created
1050                               boot options.
1051   5. Non-BlockIo Simplefile - The boot option points to a device whose handle
1052                               has SimpleFileSystem Protocol, but has no blockio
1053                               protocol. These devices do not offer blockIo
1054                               protocol, but BDS still can get the
1055                               \EFI\BOOT\boot{machinename}.EFI by SimpleFileSystem
1056                               Protocol.
1057   6. File    - The boot option points to a file. These boot options are usually
1058                created by user manually or OS loader. BDS will not delete or modify
1059                these boot options.
1060 
1061   This function will enumerate all possible boot device in the system, and
1062   automatically create boot options for Network, Shell, Removable BlockIo,
1063   and Non-BlockIo Simplefile devices.
1064   It will only execute once of every boot.
1065 
1066   @param  BdsBootOptionList      The header of the link list which indexed all
PlatformBdsLibEnumerateAllBootOption(IN OUT LIST_ENTRY * BdsBootOptionList)1067                                  current boot options
1068 
1069   @retval EFI_SUCCESS            Finished all the boot device enumerate and create
1070                                  the boot option base on that boot device
1071 
1072   @retval EFI_OUT_OF_RESOURCES   Failed to enumerate the boot device and create the boot option list
1073 **/
1074 EFI_STATUS
1075 EFIAPI
1076 PlatformBdsLibEnumerateAllBootOption (
1077   IN OUT LIST_ENTRY          *BdsBootOptionList
1078   )
1079 {
1080   EFI_STATUS                    Status;
1081   UINT16                        FloppyNumber;
1082   UINT16                        HarddriveNumber;
1083   UINT16                        CdromNumber;
1084   UINT16                        UsbNumber;
1085   UINT16                        MiscNumber;
1086   UINT16                        ScsiNumber;
1087   UINT16                        NonBlockNumber;
1088   UINTN                         NumberBlockIoHandles;
1089   EFI_HANDLE                    *BlockIoHandles;
1090   EFI_BLOCK_IO_PROTOCOL         *BlkIo;
1091   BOOLEAN                       Removable[2];
1092   UINTN                         RemovableIndex;
1093   UINTN                         Index;
1094   UINTN                         NumOfLoadFileHandles;
1095   EFI_HANDLE                    *LoadFileHandles;
1096   UINTN                         FvHandleCount;
1097   EFI_HANDLE                    *FvHandleBuffer;
1098   EFI_FV_FILETYPE               Type;
1099   UINTN                         Size;
1100   EFI_FV_FILE_ATTRIBUTES        Attributes;
1101   UINT32                        AuthenticationStatus;
1102   EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv;
1103   EFI_DEVICE_PATH_PROTOCOL      *DevicePath;
1104   UINTN                         DevicePathType;
1105   CHAR16                        Buffer[40];
1106   EFI_HANDLE                    *FileSystemHandles;
1107   UINTN                         NumberFileSystemHandles;
1108   BOOLEAN                       NeedDelete;
1109   EFI_IMAGE_DOS_HEADER          DosHeader;
1110   CHAR8                         *PlatLang;
1111   CHAR8                         *LastLang;
1112   EFI_IMAGE_OPTIONAL_HEADER_UNION       HdrData;
1113   EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION   Hdr;
1114   CHAR16                        *MacStr;
1115   CHAR16                        *IPverStr;
1116   EFI_HANDLE                    *NetworkHandles;
1117   UINTN                         BufferSize;
1118 
1119   FloppyNumber    = 0;
1120   HarddriveNumber = 0;
1121   CdromNumber     = 0;
1122   UsbNumber       = 0;
1123   MiscNumber      = 0;
1124   ScsiNumber      = 0;
1125   PlatLang        = NULL;
1126   LastLang        = NULL;
1127   ZeroMem (Buffer, sizeof (Buffer));
1128 
1129   //
1130   // If the boot device enumerate happened, just get the boot
1131   // device from the boot order variable
1132   //
1133   if (mEnumBootDevice) {
1134     GetVariable2 (LAST_ENUM_LANGUAGE_VARIABLE_NAME, &gLastEnumLangGuid, (VOID**)&LastLang, NULL);
1135     GetEfiGlobalVariable2 (L"PlatformLang", (VOID**)&PlatLang, NULL);
1136     ASSERT (PlatLang != NULL);
1137     if ((LastLang != NULL) && (AsciiStrCmp (LastLang, PlatLang) == 0)) {
1138       Status = BdsLibBuildOptionFromVar (BdsBootOptionList, L"BootOrder");
1139       FreePool (LastLang);
1140       FreePool (PlatLang);
1141       return Status;
1142     } else {
1143       Status = gRT->SetVariable (
1144         LAST_ENUM_LANGUAGE_VARIABLE_NAME,
1145         &gLastEnumLangGuid,
1146         EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE,
1147         AsciiStrSize (PlatLang),
1148         PlatLang
1149         );
1150       //
1151       // Failure to set the variable only impacts the performance next time enumerating the boot options.
1152       //
1153 
1154       if (LastLang != NULL) {
1155         FreePool (LastLang);
1156       }
1157       FreePool (PlatLang);
1158     }
1159   }
1160 
1161   //
1162   // Notes: this dirty code is to get the legacy boot option from the
1163   // BBS table and create to variable as the EFI boot option, it should
1164   // be removed after the CSM can provide legacy boot option directly
1165   //
1166   REFRESH_LEGACY_BOOT_OPTIONS;
1167 
1168   //
1169   // Delete invalid boot option
1170   //
1171   BdsDeleteAllInvalidEfiBootOption ();
1172 
1173   //
1174   // Parse removable media followed by fixed media.
1175   // The Removable[] array is used by the for-loop below to create removable media boot options
1176   // at first, and then to create fixed media boot options.
1177   //
1178   Removable[0]  = FALSE;
1179   Removable[1]  = TRUE;
1180 
1181   gBS->LocateHandleBuffer (
1182         ByProtocol,
1183         &gEfiBlockIoProtocolGuid,
1184         NULL,
1185         &NumberBlockIoHandles,
1186         &BlockIoHandles
1187         );
1188 
1189   for (RemovableIndex = 0; RemovableIndex < 2; RemovableIndex++) {
1190     for (Index = 0; Index < NumberBlockIoHandles; Index++) {
1191       Status = gBS->HandleProtocol (
1192                       BlockIoHandles[Index],
1193                       &gEfiBlockIoProtocolGuid,
1194                       (VOID **) &BlkIo
1195                       );
1196       //
1197       // skip the logical partition
1198       //
1199       if (EFI_ERROR (Status) || BlkIo->Media->LogicalPartition) {
1200         continue;
1201       }
1202 
1203       //
1204       // firstly fixed block io then the removable block io
1205       //
1206       if (BlkIo->Media->RemovableMedia == Removable[RemovableIndex]) {
1207         continue;
1208       }
1209       DevicePath  = DevicePathFromHandle (BlockIoHandles[Index]);
1210       DevicePathType = BdsGetBootTypeFromDevicePath (DevicePath);
1211 
1212       switch (DevicePathType) {
1213       case BDS_EFI_ACPI_FLOPPY_BOOT:
1214         if (FloppyNumber != 0) {
1215           UnicodeSPrint (Buffer, sizeof (Buffer), L"%s %d", BdsLibGetStringById (STRING_TOKEN (STR_DESCRIPTION_FLOPPY)), FloppyNumber);
1216         } else {
1217           UnicodeSPrint (Buffer, sizeof (Buffer), L"%s", BdsLibGetStringById (STRING_TOKEN (STR_DESCRIPTION_FLOPPY)));
1218         }
1219         BdsLibBuildOptionFromHandle (BlockIoHandles[Index], BdsBootOptionList, Buffer);
1220         FloppyNumber++;
1221         break;
1222 
1223       //
1224       // Assume a removable SATA device should be the DVD/CD device, a fixed SATA device should be the Hard Drive device.
1225       //
1226       case BDS_EFI_MESSAGE_ATAPI_BOOT:
1227       case BDS_EFI_MESSAGE_SATA_BOOT:
1228         if (BlkIo->Media->RemovableMedia) {
1229           if (CdromNumber != 0) {
1230             UnicodeSPrint (Buffer, sizeof (Buffer), L"%s %d", BdsLibGetStringById (STRING_TOKEN (STR_DESCRIPTION_CD_DVD)), CdromNumber);
1231           } else {
1232             UnicodeSPrint (Buffer, sizeof (Buffer), L"%s", BdsLibGetStringById (STRING_TOKEN (STR_DESCRIPTION_CD_DVD)));
1233           }
1234           CdromNumber++;
1235         } else {
1236           if (HarddriveNumber != 0) {
1237             UnicodeSPrint (Buffer, sizeof (Buffer), L"%s %d", BdsLibGetStringById (STRING_TOKEN (STR_DESCRIPTION_HARDDRIVE)), HarddriveNumber);
1238           } else {
1239             UnicodeSPrint (Buffer, sizeof (Buffer), L"%s", BdsLibGetStringById (STRING_TOKEN (STR_DESCRIPTION_HARDDRIVE)));
1240           }
1241           HarddriveNumber++;
1242         }
1243         DEBUG ((DEBUG_INFO | DEBUG_LOAD, "Buffer: %S\n", Buffer));
1244         BdsLibBuildOptionFromHandle (BlockIoHandles[Index], BdsBootOptionList, Buffer);
1245         break;
1246 
1247       case BDS_EFI_MESSAGE_USB_DEVICE_BOOT:
1248         if (UsbNumber != 0) {
1249           UnicodeSPrint (Buffer, sizeof (Buffer), L"%s %d", BdsLibGetStringById (STRING_TOKEN (STR_DESCRIPTION_USB)), UsbNumber);
1250         } else {
1251           UnicodeSPrint (Buffer, sizeof (Buffer), L"%s", BdsLibGetStringById (STRING_TOKEN (STR_DESCRIPTION_USB)));
1252         }
1253         BdsLibBuildOptionFromHandle (BlockIoHandles[Index], BdsBootOptionList, Buffer);
1254         UsbNumber++;
1255         break;
1256 
1257       case BDS_EFI_MESSAGE_SCSI_BOOT:
1258         if (ScsiNumber != 0) {
1259           UnicodeSPrint (Buffer, sizeof (Buffer), L"%s %d", BdsLibGetStringById (STRING_TOKEN (STR_DESCRIPTION_SCSI)), ScsiNumber);
1260         } else {
1261           UnicodeSPrint (Buffer, sizeof (Buffer), L"%s", BdsLibGetStringById (STRING_TOKEN (STR_DESCRIPTION_SCSI)));
1262         }
1263         BdsLibBuildOptionFromHandle (BlockIoHandles[Index], BdsBootOptionList, Buffer);
1264         ScsiNumber++;
1265         break;
1266 
1267       case BDS_EFI_MESSAGE_MISC_BOOT:
1268       default:
1269         if (MiscNumber != 0) {
1270           UnicodeSPrint (Buffer, sizeof (Buffer), L"%s %d", BdsLibGetStringById (STRING_TOKEN (STR_DESCRIPTION_MISC)), MiscNumber);
1271         } else {
1272           UnicodeSPrint (Buffer, sizeof (Buffer), L"%s", BdsLibGetStringById (STRING_TOKEN (STR_DESCRIPTION_MISC)));
1273         }
1274         BdsLibBuildOptionFromHandle (BlockIoHandles[Index], BdsBootOptionList, Buffer);
1275         MiscNumber++;
1276         break;
1277       }
1278     }
1279   }
1280 
1281   if (NumberBlockIoHandles != 0) {
1282     FreePool (BlockIoHandles);
1283   }
1284 
1285   //
1286   // If there is simple file protocol which does not consume block Io protocol, create a boot option for it here.
1287   //
1288   NonBlockNumber = 0;
1289   gBS->LocateHandleBuffer (
1290         ByProtocol,
1291         &gEfiSimpleFileSystemProtocolGuid,
1292         NULL,
1293         &NumberFileSystemHandles,
1294         &FileSystemHandles
1295         );
1296   for (Index = 0; Index < NumberFileSystemHandles; Index++) {
1297     Status = gBS->HandleProtocol (
1298                     FileSystemHandles[Index],
1299                     &gEfiBlockIoProtocolGuid,
1300                     (VOID **) &BlkIo
1301                     );
1302      if (!EFI_ERROR (Status)) {
1303       //
1304       //  Skip if the file system handle supports a BlkIo protocol,
1305       //
1306       continue;
1307     }
1308 
1309     //
1310     // Do the removable Media thing. \EFI\BOOT\boot{machinename}.EFI
1311     //  machinename is ia32, ia64, x64, ...
1312     //
1313     Hdr.Union  = &HdrData;
1314     NeedDelete = TRUE;
1315     Status     = BdsLibGetImageHeader (
1316                    FileSystemHandles[Index],
1317                    EFI_REMOVABLE_MEDIA_FILE_NAME,
1318                    &DosHeader,
1319                    Hdr
1320                    );
1321     if (!EFI_ERROR (Status) &&
1322         EFI_IMAGE_MACHINE_TYPE_SUPPORTED (Hdr.Pe32->FileHeader.Machine) &&
1323         Hdr.Pe32->OptionalHeader.Subsystem == EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION) {
1324       NeedDelete = FALSE;
1325     }
1326 
1327     if (NeedDelete) {
1328       //
1329       // No such file or the file is not a EFI application, delete this boot option
1330       //
1331       BdsLibDeleteOptionFromHandle (FileSystemHandles[Index]);
1332     } else {
1333       if (NonBlockNumber != 0) {
1334         UnicodeSPrint (Buffer, sizeof (Buffer), L"%s %d", BdsLibGetStringById (STRING_TOKEN (STR_DESCRIPTION_NON_BLOCK)), NonBlockNumber);
1335       } else {
1336         UnicodeSPrint (Buffer, sizeof (Buffer), L"%s", BdsLibGetStringById (STRING_TOKEN (STR_DESCRIPTION_NON_BLOCK)));
1337       }
1338       BdsLibBuildOptionFromHandle (FileSystemHandles[Index], BdsBootOptionList, Buffer);
1339       NonBlockNumber++;
1340     }
1341   }
1342 
1343   if (NumberFileSystemHandles != 0) {
1344     FreePool (FileSystemHandles);
1345   }
1346 
1347   //
1348   // Check if we have on flash shell
1349   //
1350   gBS->LocateHandleBuffer (
1351         ByProtocol,
1352         &gEfiFirmwareVolume2ProtocolGuid,
1353         NULL,
1354         &FvHandleCount,
1355         &FvHandleBuffer
1356         );
1357   for (Index = 0; Index < FvHandleCount; Index++) {
1358     gBS->HandleProtocol (
1359           FvHandleBuffer[Index],
1360           &gEfiFirmwareVolume2ProtocolGuid,
1361           (VOID **) &Fv
1362           );
1363 
1364     Status = Fv->ReadFile (
1365                   Fv,
1366                   PcdGetPtr(PcdShellFile),
1367                   NULL,
1368                   &Size,
1369                   &Type,
1370                   &Attributes,
1371                   &AuthenticationStatus
1372                   );
1373     if (EFI_ERROR (Status)) {
1374       //
1375       // Skip if no shell file in the FV
1376       //
1377       continue;
1378     }
1379     //
1380     // Build the shell boot option
1381     //
1382     BdsLibBuildOptionFromShell (FvHandleBuffer[Index], BdsBootOptionList);
1383   }
1384 
1385   if (FvHandleCount != 0) {
1386     FreePool (FvHandleBuffer);
1387   }
1388 
1389   //
1390   // Parse Network Boot Device
1391   //
1392   NumOfLoadFileHandles = 0;
1393   //
1394   // Search Load File protocol for PXE boot option.
1395   //
1396   gBS->LocateHandleBuffer (
1397         ByProtocol,
1398         &gEfiLoadFileProtocolGuid,
1399         NULL,
1400         &NumOfLoadFileHandles,
1401         &LoadFileHandles
1402         );
1403 
1404   for (Index = 0; Index < NumOfLoadFileHandles; Index++) {
1405 
1406 //
1407 //Locate EFI_DEVICE_PATH_PROTOCOL to dynamically get IPv4/IPv6 protocol information.
1408 //
1409 
1410  Status = gBS->HandleProtocol (
1411                   LoadFileHandles[Index],
1412                   &gEfiDevicePathProtocolGuid,
1413                   (VOID **) &DevicePath
1414                   );
1415 
1416  ASSERT_EFI_ERROR (Status);
1417 
1418   while (!IsDevicePathEnd (DevicePath)) {
1419     if ((DevicePath->Type == MESSAGING_DEVICE_PATH) &&
1420         (DevicePath->SubType == MSG_IPv4_DP)) {
1421 
1422   //
1423   //Get handle infomation
1424   //
1425   BufferSize = 0;
1426   NetworkHandles = NULL;
1427   Status = gBS->LocateHandle (
1428                   ByProtocol,
1429                   &gEfiSimpleNetworkProtocolGuid,
1430                   NULL,
1431                   &BufferSize,
1432                   NetworkHandles
1433                   );
1434 
1435   if (Status == EFI_BUFFER_TOO_SMALL) {
1436     NetworkHandles = AllocateZeroPool(BufferSize);
1437     if (NetworkHandles == NULL) {
1438       return (EFI_OUT_OF_RESOURCES);
1439     }
1440     Status = gBS->LocateHandle(
1441                     ByProtocol,
1442                     &gEfiSimpleNetworkProtocolGuid,
1443                     NULL,
1444                     &BufferSize,
1445                     NetworkHandles
1446                     );
1447  }
1448 
1449   //
1450   //Get the MAC string
1451   //
1452   Status = NetLibGetMacString (
1453              *NetworkHandles,
1454              NULL,
1455              &MacStr
1456              );
1457   if (EFI_ERROR (Status)) {
1458     return Status;
1459   }
1460   IPverStr = L" IPv4";
1461   UnicodeSPrint (Buffer, sizeof (Buffer), L"%s%s%s", BdsLibGetStringById (STRING_TOKEN (STR_DESCRIPTION_NETWORK)),MacStr,IPverStr);
1462   break;
1463   }
1464     if((DevicePath->Type == MESSAGING_DEVICE_PATH) &&
1465         (DevicePath->SubType == MSG_IPv6_DP)) {
1466 
1467   //
1468   //Get handle infomation
1469   //
1470   BufferSize = 0;
1471   NetworkHandles = NULL;
1472   Status = gBS->LocateHandle (
1473                   ByProtocol,
1474                   &gEfiSimpleNetworkProtocolGuid,
1475                   NULL,
1476                   &BufferSize,
1477                   NetworkHandles
1478                   );
1479 
1480   if (Status == EFI_BUFFER_TOO_SMALL) {
1481     NetworkHandles = AllocateZeroPool(BufferSize);
1482     if (NetworkHandles == NULL) {
1483        return (EFI_OUT_OF_RESOURCES);
1484     }
1485     Status = gBS->LocateHandle(
1486                     ByProtocol,
1487                     &gEfiSimpleNetworkProtocolGuid,
1488                     NULL,
1489                     &BufferSize,
1490                     NetworkHandles
1491                     );
1492  }
1493 
1494   //
1495   //Get the MAC string
1496   //
1497   Status = NetLibGetMacString (
1498              *NetworkHandles,
1499              NULL,
1500              &MacStr
1501              );
1502   if (EFI_ERROR (Status)) {
1503     return Status;
1504   }
1505       IPverStr = L" IPv6";
1506       UnicodeSPrint (Buffer, sizeof (Buffer), L"%s%s%s", BdsLibGetStringById (STRING_TOKEN (STR_DESCRIPTION_NETWORK)),MacStr,IPverStr);
1507       break;
1508     }
1509     DevicePath = NextDevicePathNode (DevicePath);
1510   }
1511 
1512     BdsLibBuildOptionFromHandle (LoadFileHandles[Index], BdsBootOptionList, Buffer);
1513   }
1514 
1515   if (NumOfLoadFileHandles != 0) {
1516     FreePool (LoadFileHandles);
1517   }
1518 
1519   //
1520   // Check if we have on flash shell
1521   //
1522  /* gBS->LocateHandleBuffer (
1523         ByProtocol,
1524         &gEfiFirmwareVolume2ProtocolGuid,
1525         NULL,
1526         &FvHandleCount,
1527         &FvHandleBuffer
1528         );
1529   for (Index = 0; Index < FvHandleCount; Index++) {
1530     gBS->HandleProtocol (
1531           FvHandleBuffer[Index],
1532           &gEfiFirmwareVolume2ProtocolGuid,
1533           (VOID **) &Fv
1534           );
1535 
1536     Status = Fv->ReadFile (
1537                   Fv,
1538                   PcdGetPtr(PcdShellFile),
1539                   NULL,
1540                   &Size,
1541                   &Type,
1542                   &Attributes,
1543                   &AuthenticationStatus
1544                   );
1545     if (EFI_ERROR (Status)) {
1546       //
1547       // Skip if no shell file in the FV
1548       //
1549       continue;
1550     }
1551     //
1552     // Build the shell boot option
1553     //
1554     BdsLibBuildOptionFromShell (FvHandleBuffer[Index], BdsBootOptionList);
1555   }
1556 
1557   if (FvHandleCount != 0) {
1558     FreePool (FvHandleBuffer);
1559   } */
1560 
1561   //
1562   // Make sure every boot only have one time
1563   // boot device enumerate
1564   //
1565   Status = BdsLibBuildOptionFromVar (BdsBootOptionList, L"BootOrder");
1566   mEnumBootDevice = TRUE;
1567 
1568   return Status;
1569 }
1570 
1571 
1572 
1573 /**
1574 
1575   The function will excute with as the platform policy, current policy
1576   is driven by boot mode. IBV/OEM can customize this code for their specific
1577   policy action.
1578 
1579   @param DriverOptionList - The header of the driver option link list
PlatformBdsPolicyBehavior(IN OUT LIST_ENTRY * DriverOptionList,IN OUT LIST_ENTRY * BootOptionList,IN PROCESS_CAPSULES ProcessCapsules,IN BASEM_MEMORY_TEST BaseMemoryTest)1580   @param  BootOptionList   - The header of the boot option link list
1581   @param ProcessCapsules  - A pointer to ProcessCapsules()
1582   @param BaseMemoryTest   - A pointer to BaseMemoryTest()
1583 
1584   @retval None.
1585 
1586 **/
1587 VOID
1588 EFIAPI
1589 PlatformBdsPolicyBehavior (
1590   IN OUT LIST_ENTRY                  *DriverOptionList,
1591   IN OUT LIST_ENTRY                  *BootOptionList,
1592   IN PROCESS_CAPSULES                ProcessCapsules,
1593   IN BASEM_MEMORY_TEST               BaseMemoryTest
1594   )
1595 {
1596   EFI_STATUS                         Status;
1597   UINT16                             Timeout;
1598   EFI_BOOT_MODE                      BootMode;
1599   BOOLEAN                            DeferredImageExist;
1600   UINTN                              Index;
1601   CHAR16                             CapsuleVarName[36];
1602   CHAR16                             *TempVarName;
1603   SYSTEM_CONFIGURATION               SystemConfiguration;
1604   UINTN                              VarSize;
1605   BOOLEAN                            SetVariableFlag;
1606   PLATFORM_PCI_DEVICE_PATH           *EmmcBootDevPath;
1607   EFI_GLOBAL_NVS_AREA_PROTOCOL       *GlobalNvsArea;
1608   EFI_HANDLE                         FvProtocolHandle;
1609   UINTN                              HandleCount;
1610   EFI_HANDLE                         *HandleBuffer;
1611   UINTN                              Index1;
1612   UINTN                              SataPciRegBase = 0;
1613   UINT16                             SataModeSelect = 0;
1614   VOID                               *RegistrationExitPmAuth = NULL;
1615   EFI_EVENT                          Event;
1616   BOOLEAN                            IsFirstBoot;
1617   UINT16                             *BootOrder;
1618   UINTN                              BootOrderSize;
1619 
1620   Timeout = PcdGet16 (PcdPlatformBootTimeOut);
1621   if (Timeout > 10 ) {
1622     //we think the Timeout variable is corrupted
1623     Timeout = 10;
1624   }
1625 
1626   VarSize = sizeof(SYSTEM_CONFIGURATION);
1627   Status = gRT->GetVariable(
1628                   NORMAL_SETUP_NAME,
1629                   &gEfiNormalSetupGuid,
1630                   NULL,
1631                   &VarSize,
1632                   &SystemConfiguration
1633                   );
1634 
1635   if (EFI_ERROR (Status) || VarSize != sizeof(SYSTEM_CONFIGURATION)) {
1636     //The setup variable is corrupted
1637     VarSize = sizeof(SYSTEM_CONFIGURATION);
1638     Status = gRT->GetVariable(
1639               L"SetupRecovery",
1640               &gEfiNormalSetupGuid,
1641               NULL,
1642               &VarSize,
1643               &SystemConfiguration
1644               );
1645     ASSERT_EFI_ERROR (Status);
1646   }
1647 
1648   //
1649   // Load the driver option as the driver option list
1650   //
1651   PlatformBdsGetDriverOption (DriverOptionList);
1652 
1653   //
1654   // Get current Boot Mode
1655   //
1656   BootMode = GetBootModeHob();
1657 
1658   //
1659   // Clear all the capsule variables CapsuleUpdateData, CapsuleUpdateData1, CapsuleUpdateData2...
1660   // as early as possible which will avoid the next time boot after the capsule update
1661   // will still into the capsule loop
1662   //
1663   StrCpy (CapsuleVarName, EFI_CAPSULE_VARIABLE_NAME);
1664   TempVarName = CapsuleVarName + StrLen (CapsuleVarName);
1665   Index = 0;
1666   SetVariableFlag = TRUE;
1667   while (SetVariableFlag) {
1668     if (Index > 0) {
1669       UnicodeValueToString (TempVarName, 0, Index, 0);
1670     }
1671     Status = gRT->SetVariable (
1672                     CapsuleVarName,
1673                     &gEfiCapsuleVendorGuid,
1674                     EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS |
1675                     EFI_VARIABLE_BOOTSERVICE_ACCESS,
1676                     0,
1677                     (VOID *)NULL
1678                     );
1679     if (EFI_ERROR (Status)) {
1680       //
1681       // There is no capsule variables, quit
1682       //
1683       SetVariableFlag = FALSE;
1684       continue;
1685     }
1686     Index++;
1687   }
1688 
1689   //
1690   // No deferred images exist by default
1691   //
1692   DeferredImageExist = FALSE;
1693   if ((BootMode != BOOT_WITH_MINIMAL_CONFIGURATION) && (PcdGet32(PcdFlashFvShellSize) > 0)){
1694     gDS->ProcessFirmwareVolume (
1695            (VOID *)(UINTN)PcdGet32(PcdFlashFvShellBase),
1696            PcdGet32(PcdFlashFvShellSize),
1697            &FvProtocolHandle
1698            );
1699   }
1700 
1701   if (SystemConfiguration.FastBoot == 1) {
1702     BootOrder = BdsLibGetVariableAndSize (
1703                   L"BootOrder",
1704                   &gEfiGlobalVariableGuid,
1705                   &BootOrderSize
1706                   );
1707     if ((BootOrder != NULL) && (BootMode != BOOT_ON_FLASH_UPDATE)) {
1708       //
1709       // BootOrder exist, it means system has boot before. We can do fast boot.
1710       //
1711       BootMode = BOOT_WITH_MINIMAL_CONFIGURATION;
1712     }
1713   }
1714 
1715 
1716   //
1717   // Use eMMC to boot OS and turn on AHCI, when SATA HDD is diconnected,
1718   // SATA AHCI CTLR device will show yellow bang, implement this solution to solve it.
1719   //
1720   SataPciRegBase  = MmPciAddress (0, 0, PCI_DEVICE_NUMBER_PCH_SATA, 0, 0);
1721   SataModeSelect  = MmioRead16 (SataPciRegBase + R_PCH_SATA_MAP) & B_PCH_SATA_MAP_SMS_MASK;
1722   Status          = EFI_SUCCESS;
1723   if (SataModeSelect != V_PCH_SATA_MAP_SMS_IDE) {
1724     Status = gBS->CreateEvent (
1725                     EVT_NOTIFY_SIGNAL,
1726                     TPL_CALLBACK,
1727                     DisableAhciCtlr,
1728                     &SataPciRegBase,
1729                     &Event
1730                      );
1731     if (!EFI_ERROR (Status)) {
1732       Status = gBS->RegisterProtocolNotify (
1733                       &gExitPmAuthProtocolGuid,
1734                       Event,
1735                       &RegistrationExitPmAuth
1736                       );
1737     }
1738   }
1739 
1740   switch (BootMode) {
1741 
1742   case BOOT_WITH_MINIMAL_CONFIGURATION:
1743     PlatformBdsInitHotKeyEvent ();
1744     PlatformBdsConnectSimpleConsole (gPlatformSimpleConsole);
1745 
1746 
1747     //
1748     // Check to see if it's needed to dispatch more DXE drivers.
1749     //
1750     for (Index = 0; Index < sizeof(ConnectDriverTable)/sizeof(EFI_GUID *); Index++) {
1751       Status = gBS->LocateHandleBuffer (
1752                       ByProtocol,
1753                       ConnectDriverTable[Index],
1754                       NULL,
1755                       &HandleCount,
1756                       &HandleBuffer
1757                       );
1758       if (!EFI_ERROR (Status)) {
1759         for (Index1 = 0; Index1 < HandleCount; Index1++) {
1760           gBS->ConnectController (
1761                  HandleBuffer[Index1],
1762                  NULL,
1763                  NULL,
1764                  TRUE
1765                  );
1766         }
1767       }
1768 
1769       if (HandleBuffer != NULL) {
1770         FreePool (HandleBuffer);
1771       }
1772 
1773       gDS->Dispatch ();
1774     }
1775 
1776     //
1777     //  Locate the Global NVS Protocol.
1778     //
1779     Status = gBS->LocateProtocol (
1780                     &gEfiGlobalNvsAreaProtocolGuid,
1781                     NULL,
1782                     (void **)&GlobalNvsArea
1783                     );
1784     if (GlobalNvsArea->Area->emmcVersion == 0){
1785       EmmcBootDevPath = (PLATFORM_PCI_DEVICE_PATH *)gPlatformSimpleBootOption[0];
1786       EmmcBootDevPath->PciDevice.Device = 0x10;
1787     }
1788 
1789     //
1790     // Connect boot device here to give time to read keyboard.
1791     //
1792     BdsLibConnectDevicePath (gPlatformSimpleBootOption[0]);
1793 
1794     //
1795     // This is a workround for dectecting hotkey from USB keyboard.
1796     //
1797     gBS->Stall(KEYBOARD_TIMER_INTERVAL);
1798 
1799     if (mHotKeyTimerEvent != NULL) {
1800       gBS->SetTimer (
1801              mHotKeyTimerEvent,
1802              TimerCancel,
1803              0
1804              );
1805       gBS->CloseEvent (mHotKeyTimerEvent);
1806       mHotKeyTimerEvent = NULL;
1807     }
1808     if (mHotKeyPressed) {
1809       //
1810       // Skip show progress count down
1811       //
1812       Timeout = 0xFFFF;
1813       goto FULL_CONFIGURATION;
1814     }
1815 
1816     if (SystemConfiguration.QuietBoot) {
1817       EnableQuietBoot (PcdGetPtr(PcdLogoFile));
1818     } else {
1819       PlatformBdsDiagnostics (IGNORE, FALSE, BaseMemoryTest);
1820     }
1821 
1822 
1823     #ifdef TPM_ENABLED
1824     TcgPhysicalPresenceLibProcessRequest();
1825     #endif
1826     #ifdef FTPM_ENABLE
1827     TrEEPhysicalPresenceLibProcessRequest(NULL);
1828     #endif
1829     //
1830     // Close boot script and install ready to lock
1831     //
1832     InstallReadyToLock ();
1833 
1834     //
1835     // Give one chance to enter the setup if we
1836     // select Gummiboot "Reboot Into Firmware Interface" and Fast Boot is enabled.
1837     //
1838     BootIntoFirmwareInterface();
1839     break;
1840 
1841   case BOOT_ASSUMING_NO_CONFIGURATION_CHANGES:
1842 
1843     //
1844     // In no-configuration boot mode, we can connect the
1845     // console directly.
1846     //
1847     BdsLibConnectAllDefaultConsoles ();
1848     PlatformBdsDiagnostics (IGNORE, TRUE, BaseMemoryTest);
1849 
1850     //
1851     // Perform some platform specific connect sequence
1852     //
1853     PlatformBdsConnectSequence ();
1854 
1855     //
1856     // As console is ready, perform user identification again.
1857     //
1858     if (mCurrentUser == NULL) {
1859       PlatformBdsUserIdentify (&mCurrentUser, &DeferredImageExist);
1860       if (DeferredImageExist) {
1861         //
1862         // After user authentication, the deferred drivers was loaded again.
1863         // Here, need to ensure the deferred images are connected.
1864         //
1865         BdsLibConnectAllDefaultConsoles ();
1866         PlatformBdsConnectSequence ();
1867       }
1868     }
1869 
1870     //
1871     // Close boot script and install ready to lock
1872     //
1873     InstallReadyToLock ();
1874 
1875     //
1876     // Notes: current time out = 0 can not enter the
1877     // front page
1878     //
1879     PlatformBdsEnterFrontPageWithHotKey (Timeout, FALSE);
1880 
1881     //
1882     // Check the boot option with the boot option list
1883     //
1884     BdsLibBuildOptionFromVar (BootOptionList, L"BootOrder");
1885     break;
1886 
1887   case BOOT_ON_FLASH_UPDATE:
1888 
1889     //
1890     // Boot with the specific configuration
1891     //
1892     PlatformBdsConnectConsole (gPlatformConsole);
1893     PlatformBdsDiagnostics (EXTENSIVE, FALSE, BaseMemoryTest);
1894     BdsLibConnectAll ();
1895 
1896     //
1897     // Perform user identification
1898     //
1899     if (mCurrentUser == NULL) {
1900       PlatformBdsUserIdentify (&mCurrentUser, &DeferredImageExist);
1901       if (DeferredImageExist) {
1902         //
1903         // After user authentication, the deferred drivers was loaded again.
1904         // Here, need to ensure the deferred images are connected.
1905         //
1906         BdsLibConnectAll ();
1907       }
1908     }
1909 
1910     //
1911     // Close boot script and install ready to lock
1912     //
1913     InstallReadyToLock ();
1914 
1915     ProcessCapsules (BOOT_ON_FLASH_UPDATE);
1916     break;
1917 
1918   case BOOT_IN_RECOVERY_MODE:
1919 
1920     //
1921     // In recovery mode, just connect platform console
1922     // and show up the front page
1923     //
1924     PlatformBdsConnectConsole (gPlatformConsole);
1925     PlatformBdsDiagnostics (EXTENSIVE, FALSE, BaseMemoryTest);
1926     BdsLibConnectAll ();
1927 
1928     //
1929     // Perform user identification
1930     //
1931     if (mCurrentUser == NULL) {
1932       PlatformBdsUserIdentify (&mCurrentUser, &DeferredImageExist);
1933       if (DeferredImageExist) {
1934         //
1935         // After user authentication, the deferred drivers was loaded again.
1936         // Here, need to ensure the deferred drivers are connected.
1937         //
1938         BdsLibConnectAll ();
1939       }
1940     }
1941 
1942     //
1943     // Close boot script and install ready to lock
1944     //
1945     InstallReadyToLock ();
1946 
1947     //
1948     // In recovery boot mode, we still enter to the
1949     // frong page now
1950     //
1951     PlatformBdsEnterFrontPageWithHotKey (Timeout, FALSE);
1952     break;
1953 
1954 FULL_CONFIGURATION:
1955   case BOOT_WITH_FULL_CONFIGURATION:
1956   case BOOT_WITH_FULL_CONFIGURATION_PLUS_DIAGNOSTICS:
1957   case BOOT_WITH_DEFAULT_SETTINGS:
1958   default:
1959 
1960     //
1961     // Connect platform console
1962     //
1963     Status = PlatformBdsConnectConsole (gPlatformConsole);
1964     if (EFI_ERROR (Status)) {
1965 
1966       //
1967       // Here OEM/IBV can customize with defined action
1968       //
1969       PlatformBdsNoConsoleAction ();
1970     }
1971 
1972     //
1973     // Chenyunh[TODO]: This is Workgroud to show the fs for uSDcard,
1974     // Need to root cause this issue.
1975     //
1976     DEBUG ((DEBUG_ERROR, "Start to reconnect all driver.\n"));
1977     BdsLibDisconnectAllEfi();
1978     BdsLibConnectAll ();
1979     DEBUG ((DEBUG_ERROR, "End to reconnect all driver.\n"));
1980 
1981     //
1982     // Perform some platform specific connect sequence
1983     //
1984     PlatformBdsConnectSequence ();
1985     if (SystemConfiguration.QuietBoot) {
1986         EnableQuietBoot (PcdGetPtr(PcdLogoFile));
1987     } else {
1988         PlatformBdsDiagnostics (IGNORE, FALSE, BaseMemoryTest);
1989     }
1990 
1991     //
1992     // Do a pre-delay so Hard Disk can spin up and see more logo.
1993     //
1994     gBS->Stall(SystemConfiguration.HddPredelay * 1000000);
1995 
1996     //
1997     // Perform user identification
1998     //
1999     if (mCurrentUser == NULL) {
2000       PlatformBdsUserIdentify (&mCurrentUser, &DeferredImageExist);
2001       if (DeferredImageExist) {
2002         //
2003         // After user authentication, the deferred drivers was loaded again.
2004         // Here, need to ensure the deferred drivers are connected.
2005         //
2006         Status = PlatformBdsConnectConsole (gPlatformConsole);
2007         if (EFI_ERROR (Status)) {
2008           PlatformBdsNoConsoleAction ();
2009         }
2010         PlatformBdsConnectSequence ();
2011       }
2012     }
2013    #ifdef TPM_ENABLED
2014    TcgPhysicalPresenceLibProcessRequest();
2015    #endif
2016    #ifdef FTPM_ENABLE
2017    TrEEPhysicalPresenceLibProcessRequest(NULL);
2018    #endif
2019     //
2020     // Close boot script and install ready to lock
2021     //
2022     InstallReadyToLock ();
2023 
2024     //
2025     // Here we have enough time to do the enumeration of boot device
2026     //
2027     PlatformBdsLibEnumerateAllBootOption (BootOptionList);
2028 
2029     //
2030     // Give one chance to enter the setup if we
2031     // have the time out
2032     //
2033     PlatformBdsEnterFrontPageWithHotKey (Timeout, FALSE);
2034 
2035 	//
2036 	// Give one chance to enter the setup if we
2037 	// select Gummiboot "Reboot Into Firmware Interface"
2038 	//
2039 	BootIntoFirmwareInterface();
2040 
2041     //
2042     // In default boot mode, always find all boot
2043     // option and do enumerate all the default boot option
2044     //
2045     if (Timeout == 0) {
2046       BdsLibBuildOptionFromVar (BootOptionList, L"BootOrder");
2047       if (IsListEmpty(BootOptionList)) {
2048         PlatformBdsPredictBootOption (BootOptionList);
2049       }
2050 
2051       return;
2052     }
2053 
2054 
2055     break;
2056   }
2057 
2058 
2059   IsFirstBoot = PcdGetBool(PcdBootState);
2060   if (IsFirstBoot) {
2061     PcdSetBool(PcdBootState, FALSE);
2062   }
2063   return;
2064 
2065 }
2066 
2067 /**
2068   Hook point after a boot attempt succeeds. We don't expect a boot option to
2069   return, so the UEFI 2.0 specification defines that you will default to an
2070   interactive mode and stop processing the BootOrder list in this case. This
PlatformBdsBootSuccess(IN BDS_COMMON_OPTION * Option)2071   is alos a platform implementation and can be customized by IBV/OEM.
2072 
2073   @param Option  Pointer to Boot Option that succeeded to boot.
2074 
2075   @retval None.
2076 
2077 **/
2078 VOID
2079 EFIAPI
2080 PlatformBdsBootSuccess (
2081   IN  BDS_COMMON_OPTION *Option
2082   )
2083 {
2084   CHAR16  *TmpStr;
2085 
2086   //
2087   // If Boot returned with EFI_SUCCESS and there is not in the boot device
2088   // select loop then we need to pop up a UI and wait for user input.
2089   //
2090   TmpStr =  Option->StatusString;
2091   if (TmpStr != NULL) {
2092     BdsLibOutputStrings (gST->ConOut, TmpStr, Option->Description, L"\n\r", NULL);
2093     FreePool(TmpStr);
2094   }
2095 }
2096 
2097 /**
2098   Hook point after a boot attempt fails.
2099 
2100   @param Option - Pointer to Boot Option that failed to boot.
PlatformBdsBootFail(IN BDS_COMMON_OPTION * Option,IN EFI_STATUS Status,IN CHAR16 * ExitData,IN UINTN ExitDataSize)2101   @param Status - Status returned from failed boot.
2102   @param ExitData - Exit data returned from failed boot.
2103   @param ExitDataSize - Exit data size returned from failed boot.
2104 
2105   @retval None.
2106 
2107 **/
2108 VOID
2109 EFIAPI
2110 PlatformBdsBootFail (
2111   IN  BDS_COMMON_OPTION  *Option,
2112   IN  EFI_STATUS         Status,
2113   IN  CHAR16             *ExitData,
2114   IN  UINTN              ExitDataSize
2115   )
2116 {
2117   CHAR16          *TmpStr;
2118   EFI_HANDLE      FvProtocolHandle;
2119 
2120   //
2121   // If Boot returned with failed status then we need to pop up a UI and wait
2122   // for user input.
2123   //
2124   TmpStr = Option->StatusString;
2125   if (TmpStr != NULL) {
2126     BdsLibOutputStrings (gST->ConOut, TmpStr, Option->Description, L"\n\r", NULL);
2127     FreePool(TmpStr);
2128   }
2129   if (PcdGet32(PcdFlashFvShellSize) > 0){
2130     gDS->ProcessFirmwareVolume (
2131            (VOID *)(UINTN)PcdGet32(PcdFlashFvShellBase),
2132            PcdGet32(PcdFlashFvShellSize),
2133            &FvProtocolHandle
2134            );
2135   }
2136   PlatformBdsConnectSequence ();
2137 }
2138 
2139 /**
PlatformBdsNoConsoleAction(VOID)2140   This function is remained for IBV/OEM to do some platform action,
2141   if there no console device can be connected.
2142 
2143   @param  None.
2144 
2145   @retval EFI_SUCCESS       Direct return success now.
2146 
2147 **/
2148 EFI_STATUS
2149 PlatformBdsNoConsoleAction (
2150   VOID
2151   )
2152 {
2153   return EFI_SUCCESS;
2154 }
2155 
2156 /**
2157   This function locks the block
2158 
2159   @param Base            The base address flash region to be locked.
2160 
2161 **/
2162 VOID
2163 BdsLockFv (
2164   IN EFI_PHYSICAL_ADDRESS  Base
2165   )
2166 {
2167   EFI_FV_BLOCK_MAP_ENTRY      *BlockMap;
2168   EFI_FIRMWARE_VOLUME_HEADER  *FvHeader;
2169   EFI_PHYSICAL_ADDRESS        BaseAddress;
2170   UINT8                       Data;
2171   UINT32                      BlockLength;
2172   UINTN                       Index;
2173 
2174   BaseAddress = Base - 0x400000 + 2;
2175   FvHeader    = (EFI_FIRMWARE_VOLUME_HEADER *) ((UINTN) (Base));
2176   BlockMap    = &(FvHeader->BlockMap[0]);
2177 
2178   while ((BlockMap->NumBlocks != 0) && (BlockMap->Length != 0)) {
2179     BlockLength = BlockMap->Length;
2180     for (Index = 0; Index < BlockMap->NumBlocks; Index++) {
PlatformBdsLockNonUpdatableFlash(VOID)2181       Data = MmioOr8 ((UINTN) BaseAddress, 0x03);
2182       BaseAddress += BlockLength;
2183     }
2184     BlockMap++;
2185   }
2186 }
2187 
2188 VOID
2189 EFIAPI
2190 PlatformBdsLockNonUpdatableFlash (
2191   VOID
2192   )
2193 {
2194   EFI_PHYSICAL_ADDRESS  Base;
2195 
2196   Base = (EFI_PHYSICAL_ADDRESS) PcdGet32 (PcdFlashFvMainBase);
2197   if (Base > 0) {
2198     BdsLockFv (Base);
2199   }
2200 
2201   Base = (EFI_PHYSICAL_ADDRESS) PcdGet32 (PcdFlashFvRecoveryBase);
2202   if (Base > 0) {
2203     BdsLockFv (Base);
2204   }
2205 }
2206 
2207 /**
2208   Lock the ConsoleIn device in system table. All key
2209   presses will be ignored until the Password is typed in. The only way to
2210   disable the password is to type it in to a ConIn device.
LockKeyboards(IN CHAR16 * Password)2211 
2212   @param  Password        Password used to lock ConIn device.
2213 
2214   @retval EFI_SUCCESS     lock the Console In Spliter virtual handle successfully.
2215   @retval EFI_UNSUPPORTED Password not found
2216 
2217 **/
2218 EFI_STATUS
2219 EFIAPI
2220 LockKeyboards (
2221   IN  CHAR16    *Password
2222   )
2223 {
2224     return EFI_UNSUPPORTED;
2225 }
2226 
2227 /**
PlatformBdsConnectAuthDevice(VOID)2228   Connect the predefined platform default authentication devices.
2229 
2230   This function connects the predefined device path for authentication device,
2231   and if the predefined device path has child device path, the child handle will
2232   be connected too. But the child handle of the child will not be connected.
2233 
2234 **/
2235 VOID
2236 EFIAPI
2237 PlatformBdsConnectAuthDevice (
2238   VOID
2239   )
2240 {
2241   EFI_STATUS                   Status;
2242   UINTN                        Index;
2243   UINTN                        HandleIndex;
2244   UINTN                        HandleCount;
2245   EFI_HANDLE                   *HandleBuffer;
2246   EFI_DEVICE_PATH_PROTOCOL     *ChildDevicePath;
2247   EFI_USER_MANAGER_PROTOCOL    *Manager;
2248 
2249   Status = gBS->LocateProtocol (
2250                   &gEfiUserManagerProtocolGuid,
2251                   NULL,
2252                   (VOID **) &Manager
2253                   );
2254   if (EFI_ERROR (Status)) {
2255     //
2256     // As user manager protocol is not installed, the authentication devices
2257     // should not be connected.
2258     //
2259     return ;
2260   }
2261 
2262   Index = 0;
2263   while (gUserAuthenticationDevice[Index] != NULL) {
2264     //
2265     // Connect the platform customized device paths
2266     //
2267     BdsLibConnectDevicePath (gUserAuthenticationDevice[Index]);
2268     Index++;
2269   }
2270 
2271   //
2272   // Find and connect the child device paths of the platform customized device paths
2273   //
2274   HandleBuffer = NULL;
2275   for (Index = 0; gUserAuthenticationDevice[Index] != NULL; Index++) {
2276     HandleCount = 0;
2277     Status = gBS->LocateHandleBuffer (
2278                     AllHandles,
2279                     NULL,
2280                     NULL,
2281                     &HandleCount,
2282                     &HandleBuffer
2283                     );
2284     ASSERT (!EFI_ERROR (Status));
2285 
2286     //
2287     // Find and connect the child device paths of gUserIdentificationDevice[Index]
2288     //
2289     for (HandleIndex = 0; HandleIndex < HandleCount; HandleIndex++) {
2290       ChildDevicePath = NULL;
2291       Status = gBS->HandleProtocol (
2292                       HandleBuffer[HandleIndex],
2293                       &gEfiDevicePathProtocolGuid,
2294                       (VOID **) &ChildDevicePath
2295                       );
2296       if (EFI_ERROR (Status) || ChildDevicePath == NULL) {
2297         continue;
2298       }
2299 
2300       if (CompareMem (
2301             ChildDevicePath,
2302             gUserAuthenticationDevice[Index],
2303             (GetDevicePathSize (gUserAuthenticationDevice[Index]) - sizeof (EFI_DEVICE_PATH_PROTOCOL))
2304             ) != 0) {
2305         continue;
2306       }
2307       gBS->ConnectController (
2308              HandleBuffer[HandleIndex],
2309              NULL,
2310              NULL,
2311              TRUE
2312              );
2313     }
2314   }
2315 
2316   if (HandleBuffer != NULL) {
2317     FreePool (HandleBuffer);
2318   }
2319 }
2320 
2321 /**
PlatformBdsUserIdentify(OUT EFI_USER_PROFILE_HANDLE * User,OUT BOOLEAN * DeferredImageExist)2322   This function is to identify a user, and return whether deferred images exist.
2323 
2324   @param[out]  User               Point to user profile handle.
2325   @param[out]  DeferredImageExist On return, points to TRUE if the deferred image
2326                                   exist or FALSE if it did not exist.
2327 
2328 **/
2329 VOID
2330 EFIAPI
2331 PlatformBdsUserIdentify (
2332   OUT EFI_USER_PROFILE_HANDLE        *User,
2333   OUT BOOLEAN                        *DeferredImageExist
2334   )
2335 {
2336   EFI_STATUS                         Status;
2337   EFI_DEFERRED_IMAGE_LOAD_PROTOCOL   *DeferredImage;
2338   UINTN                              HandleCount;
2339   EFI_HANDLE                         *HandleBuf;
2340   UINTN                              Index;
2341   UINTN                              DriverIndex;
2342   EFI_DEVICE_PATH_PROTOCOL           *ImageDevicePath;
2343   VOID                               *DriverImage;
2344   UINTN                              ImageSize;
2345   BOOLEAN                            BootOption;
2346 
2347   //
2348   // Perform user identification
2349   //
2350   do {
2351     Status = BdsLibUserIdentify (User);
2352   } while (EFI_ERROR (Status));
2353 
2354   //
2355   // After user authentication now, try to find whether deferred image exists
2356   //
2357   HandleCount = 0;
2358   HandleBuf   = NULL;
2359   *DeferredImageExist = FALSE;
2360   Status = gBS->LocateHandleBuffer (
2361                   ByProtocol,
2362                   &gEfiDeferredImageLoadProtocolGuid,
2363                   NULL,
2364                   &HandleCount,
2365                   &HandleBuf
2366                   );
2367   if (EFI_ERROR (Status)) {
2368     return ;
2369   }
2370 
2371   for (Index = 0; Index < HandleCount; Index++) {
2372     Status = gBS->HandleProtocol (
2373                     HandleBuf[Index],
2374                     &gEfiDeferredImageLoadProtocolGuid,
2375                     (VOID **) &DeferredImage
2376                     );
2377     if (!EFI_ERROR (Status)) {
2378       //
2379       // Find whether deferred image exists in this instance.
2380       //
2381       DriverIndex = 0;
2382       Status = DeferredImage->GetImageInfo(
2383                                 DeferredImage,
2384                                 DriverIndex,
2385                                 &ImageDevicePath,
2386                                 (VOID **) &DriverImage,
2387                                 &ImageSize,
2388                                 &BootOption
2389                                 );
2390       if (!EFI_ERROR (Status)) {
2391         //
2392         // The deferred image is found.
2393         //
2394         FreePool (HandleBuf);
2395         *DeferredImageExist = TRUE;
2396         return ;
2397       }
2398     }
2399   }
2400 
2401   FreePool (HandleBuf);
2402 }
2403 
2404 UINTN gHotKey = 0;
2405 
2406 
2407 EFI_STATUS
2408 ShowProgressHotKey (
2409   IN UINT16                       TimeoutDefault
2410   )
2411 {
2412   CHAR16                        *TmpStr;
2413   UINT16                        TimeoutRemain;
2414   EFI_STATUS                    Status;
2415   EFI_INPUT_KEY                 Key;
2416   EFI_GRAPHICS_OUTPUT_BLT_PIXEL Foreground;
2417   EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background;
2418   EFI_GRAPHICS_OUTPUT_BLT_PIXEL Color;
2419   UINT32                        GpioValue;
2420 
2421   if (TimeoutDefault == 0) {
2422     return EFI_TIMEOUT;
2423   }
2424 
2425   gST->ConOut->SetAttribute(gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));
2426 
2427   if (DebugAssertEnabled())
2428   {
2429     DEBUG ((EFI_D_INFO, "\n\nStart showing progress bar... Press any key to stop it, or press <F2> or <DEL> to enter setup page! ...Zzz....\n"));
2430   }
2431   else
2432   {
2433     #ifdef __GNUC__
2434     SerialPortWrite((UINT8 *)"\n\n>>>>Start boot option, Press <F2> or <DEL> to enter setup page(5 Sec)[GCC]", 76);
2435     #else
2436     SerialPortWrite((UINT8 *)"\n\n>>>>Start boot option, Press <F2> or <DEL> to enter setup page(5 Sec)", 71);
2437     #endif
2438   }
2439   SetMem (&Foreground, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0xff);
2440   SetMem (&Background, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0x0);
2441   SetMem (&Color, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0xff);
2442 
2443   //
2444   // Clear the progress status bar first
2445   //
2446   TmpStr = L"Start boot option, Press <F2> or <DEL> to enter setup page.";
2447   PlatformBdsShowProgress (Foreground, Background, TmpStr, Color, 0, 0);
2448 
2449   TimeoutRemain = TimeoutDefault;
2450   while (TimeoutRemain != 0) {
2451     if (DebugAssertEnabled())
2452     {
2453     DEBUG ((EFI_D_INFO, "Showing progress bar...Remaining %d second!\n", TimeoutRemain));
2454     }
2455     else
2456     {
2457     SerialPortWrite ((UINT8 *)".", 1);
2458     }
2459     Status = WaitForSingleEvent (gST->ConIn->WaitForKey, ONE_SECOND);
2460     if (Status != EFI_TIMEOUT) {
2461       break;
2462     }
2463     TimeoutRemain--;
2464 
2465     //
2466     // Show progress
2467     //
2468     if (TmpStr != NULL) {
2469       PlatformBdsShowProgress (
2470         Foreground,
2471         Background,
2472         TmpStr,
2473         Color,
2474         ((TimeoutDefault - TimeoutRemain) * 100 / TimeoutDefault),
2475         0
2476         );
2477     }
2478   }
2479 
2480   //
2481   // Timeout expired
2482   //
2483   if (TimeoutRemain == 0) {
2484     if (DebugAssertEnabled())
2485 	{
2486 	}
2487     else
2488     {
2489     SerialPortWrite ((UINT8 *)"\r\n", 2);
2490     }
2491     return EFI_TIMEOUT;
2492   }
2493 
2494   //
2495   // User pressed some key
2496   //
2497   Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
2498   if (EFI_ERROR (Status)) {
2499     return Status;
2500   }
2501 
2502   //
2503   // Check Volume Up Key to enter Setup
2504   //
2505   GpioValue = MmioRead32 (IO_BASE_ADDRESS + 0x0668);  // The value of GPIOC_5
2506   if (((GpioValue & BIT0) == 0) && (Key.ScanCode == SCAN_UP)) {
2507     gHotKey = 0;
2508     return EFI_SUCCESS;
2509   }
2510 
2511   if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) {
2512     //
2513     // User pressed enter, equivalent to select "continue"
2514     //
2515     return EFI_TIMEOUT;
2516   }
2517 
2518   //
2519   //F2 --  Front Page
2520   //F5 --  Device Manager
2521   //F7 --  Boot Manager
2522   // do not use F8. generally people assume it is windows safe mode key.
2523   //F9 --  Boot order
2524   //
2525   DEBUG ((EFI_D_INFO, "[Key Pressed]: ScanCode 0x%x\n", Key.ScanCode));
2526   switch(Key.ScanCode) {
2527       case SCAN_F2:
2528           gHotKey = 0;
2529           break;
2530 
2531       case SCAN_DELETE:
2532           gHotKey = 0;
2533           break;
2534 
2535       case SCAN_F5:
2536           gHotKey = FRONT_PAGE_KEY_DEVICE_MANAGER;
2537           break;
2538 
2539       case SCAN_F7:
2540           gHotKey = FRONT_PAGE_KEY_BOOT_MANAGER;
2541           break;
2542 
2543       case SCAN_F9:
2544           gHotKey = FRONT_PAGE_KEY_BOOT_MAINTAIN;
2545           break;
2546 
2547       default:
2548           //set gHotKey to continue so that flow will not go into CallFrontPage
2549           gHotKey = FRONT_PAGE_KEY_CONTINUE;
2550           return EFI_TIMEOUT;
2551           break;
2552   }
2553 
2554   return EFI_SUCCESS;
2555 }
2556 
2557 
2558 
2559 /**
2560   This function is the main entry of the platform setup entry.
2561   The function will present the main menu of the system setup,
2562   this is the platform reference part and can be customize.
PlatformBdsEnterFrontPageWithHotKey(IN UINT16 TimeoutDefault,IN BOOLEAN ConnectAllHappened)2563 
2564 
2565   @param TimeoutDefault     The fault time out value before the system
2566                             continue to boot.
2567   @param ConnectAllHappened The indicater to check if the connect all have
2568                             already happened.
2569 
2570 **/
2571 VOID
2572 PlatformBdsEnterFrontPageWithHotKey (
2573   IN UINT16                       TimeoutDefault,
2574   IN BOOLEAN                      ConnectAllHappened
2575   )
2576 {
2577   EFI_STATUS                    Status;
2578 
2579   EFI_GRAPHICS_OUTPUT_PROTOCOL       *GraphicsOutput;
2580   EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL    *SimpleTextOut;
2581   UINTN                              BootTextColumn;
2582   UINTN                              BootTextRow;
2583 
2584   GraphicsOutput = NULL;
2585   SimpleTextOut = NULL;
2586 
2587   PERF_START (NULL, "BdsTimeOut", "BDS", 0);
2588 
2589   //
2590   // Indicate if we need connect all in the platform setup
2591   //
2592   if (ConnectAllHappened) {
2593     gConnectAllHappened = TRUE;
2594   }
2595 
2596   if (!mModeInitialized) {
2597     //
2598     // After the console is ready, get current video resolution
2599     // and text mode before launching setup at first time.
2600     //
2601     Status = gBS->HandleProtocol (
2602                     gST->ConsoleOutHandle,
2603                     &gEfiGraphicsOutputProtocolGuid,
2604                     (VOID**)&GraphicsOutput
2605                     );
2606     if (EFI_ERROR (Status)) {
2607       GraphicsOutput = NULL;
2608     }
2609 
2610     Status = gBS->HandleProtocol (
2611                     gST->ConsoleOutHandle,
2612                     &gEfiSimpleTextOutProtocolGuid,
2613                     (VOID**)&SimpleTextOut
2614                     );
2615     if (EFI_ERROR (Status)) {
2616       SimpleTextOut = NULL;
2617     }
2618 
2619     if (GraphicsOutput != NULL) {
2620       //
2621       // Get current video resolution and text mode.
2622       //
2623       mBootHorizontalResolution = GraphicsOutput->Mode->Info->HorizontalResolution;
2624       mBootVerticalResolution   = GraphicsOutput->Mode->Info->VerticalResolution;
2625     }
2626 
2627     if (SimpleTextOut != NULL) {
2628       Status = SimpleTextOut->QueryMode (
2629                                 SimpleTextOut,
2630                                 SimpleTextOut->Mode->Mode,
2631                                 &BootTextColumn,
2632                                 &BootTextRow
2633                                 );
2634       mBootTextModeColumn = (UINT32)BootTextColumn;
2635       mBootTextModeRow    = (UINT32)BootTextRow;
2636     }
2637 
2638     //
2639     // Get user defined text mode for setup.
2640     //
2641     mSetupHorizontalResolution = PcdGet32 (PcdSetupVideoHorizontalResolution);
2642     mSetupVerticalResolution   = PcdGet32 (PcdSetupVideoVerticalResolution);
2643     mSetupTextModeColumn       = PcdGet32 (PcdSetupConOutColumn);
2644     mSetupTextModeRow          = PcdGet32 (PcdSetupConOutRow);
2645 
2646     mModeInitialized           = TRUE;
2647   }
2648 
2649   if (TimeoutDefault != 0xffff) {
2650     Status = ShowProgressHotKey (TimeoutDefault);
2651 
2652     //
2653     // Ensure screen is clear when switch Console from Graphics mode to Text mode
2654     //
2655     gST->ConOut->EnableCursor (gST->ConOut, TRUE);
2656     gST->ConOut->ClearScreen (gST->ConOut);
2657 
2658     if (EFI_ERROR (Status)) {
2659       //
2660       // Timeout or user press enter to continue
2661       //
2662       goto Exit;
2663     }
2664   }
2665   //
2666   // Install BM HiiPackages.
2667   // Keep BootMaint HiiPackage, so that it can be covered by global setting.
2668   //
2669 	InitBMPackage ();
2670   do {
2671 
2672     BdsSetConsoleMode (TRUE);
2673 
2674     InitializeFrontPage (FALSE);
2675 
2676     //
2677     // Update Front Page strings
2678     //
2679     UpdateFrontPageStrings ();
2680 
2681     Status = EFI_SUCCESS;
2682     gCallbackKey = 0;
2683     if (gHotKey == 0) {
2684       Status = CallFrontPage ();
2685     } else {
2686       gCallbackKey = gHotKey;
2687       gHotKey = 0;
2688     }
2689 
2690     //
2691     // If gCallbackKey is greater than 1 and less or equal to 5,
2692     // it will launch configuration utilities.
2693     // 2 = set language
2694     // 3 = boot manager
2695     // 4 = device manager
2696     // 5 = boot maintenance manager
2697     //
2698     if (gCallbackKey != 0) {
2699       REPORT_STATUS_CODE (
2700         EFI_PROGRESS_CODE,
2701         (EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_PC_USER_SETUP)
2702         );
2703     }
2704 
2705     //
2706     // Based on the key that was set, we can determine what to do
2707     //
2708     switch (gCallbackKey) {
2709     //
2710     // The first 4 entries in the Front Page are to be GUARANTEED to remain constant so IHV's can
2711     // describe to their customers in documentation how to find their setup information (namely
2712     // under the device manager and specific buckets)
2713     //
2714     // These entries consist of the Continue, Select language, Boot Manager, and Device Manager
2715     //
2716     case FRONT_PAGE_KEY_CONTINUE:
2717 
2718       //
2719       // User hit continue
2720       //
2721       break;
2722 
2723     case FRONT_PAGE_KEY_LANGUAGE:
2724 
2725       //
2726       // User made a language setting change - display front page again
2727       //
2728       break;
2729 
2730     case FRONT_PAGE_KEY_BOOT_MANAGER:
2731       //
2732 	  // Remove the installed BootMaint HiiPackages when exit.
2733       //
2734       FreeBMPackage ();
2735 
2736       //
2737       // User chose to run the Boot Manager
2738       //
2739       CallBootManager ();
2740 
2741 	  //
2742       // Reinstall BootMaint HiiPackages after exiting from Boot Manager.
2743       //
2744       InitBMPackage ();
2745       break;
2746 
2747     case FRONT_PAGE_KEY_DEVICE_MANAGER:
2748 
2749       //
2750       // Display the Device Manager
2751       //
2752       do {
2753         CallDeviceManager ();
2754       } while (gCallbackKey == FRONT_PAGE_KEY_DEVICE_MANAGER);
2755       break;
2756 
2757     case FRONT_PAGE_KEY_BOOT_MAINTAIN:
2758 
2759       //
2760       // Display the Boot Maintenance Manager
2761       //
2762       BdsStartBootMaint ();
2763       break;
2764     }
2765 
2766   } while (((UINTN)gCallbackKey) != FRONT_PAGE_KEY_CONTINUE);
2767 
2768   //
2769   //Will leave browser, check any reset required change is applied? if yes, reset system
2770   //
2771   SetupResetReminder ();
2772   //
2773   // Remove the installed BootMaint HiiPackages when exit.
2774   //
2775   FreeBMPackage ();
2776 
2777 Exit:
2778   //
2779   // Automatically load current entry
2780   // Note: The following lines of code only execute when Auto boot
2781   // takes affect
2782   //
2783   PERF_END (NULL, "BdsTimeOut", "BDS", 0);
2784 }
2785 
2786 
2787 VOID
2788 BootIntoFirmwareInterface(
2789 VOID
2790 )
2791 {
2792   EFI_STATUS        Status;
2793   UINTN             DataSize;
2794   UINT16            Timeout;
2795   UINT64            OsIndication;
2796 
2797 
2798   OsIndication = 0;
2799   DataSize = sizeof(UINT64);
2800   Status = gRT->GetVariable (
2801                   L"OsIndications",
2802                   &gEfiGlobalVariableGuid,
2803                   NULL,
2804                   &DataSize,
2805                   &OsIndication
2806                   );
2807 
2808   DEBUG ((EFI_D_INFO, "OSIndication Variable Value %d\n", OsIndication));
2809   //
2810   //Goto FrontPage directly when bit EFI_OS_INDICATIONS_BOOT_TO_FW_UI in OSIndication Variable is setted.
PlatformBdsConnectSimpleConsole(IN BDS_CONSOLE_CONNECT_ENTRY * PlatformConsole)2811   //
2812   if (!EFI_ERROR(Status) && (OsIndication != 0)) {
2813    Timeout = 0xffff;
2814    PlatformBdsEnterFrontPage (Timeout, FALSE);
2815    }
2816 }
2817 
2818 
2819 EFI_STATUS
2820 PlatformBdsConnectSimpleConsole (
2821   IN BDS_CONSOLE_CONNECT_ENTRY   *PlatformConsole
2822 )
2823 {
2824   EFI_STATUS                         Status;
2825   UINTN                              Index;
2826   EFI_DEVICE_PATH_PROTOCOL           *VarConout;
2827   EFI_DEVICE_PATH_PROTOCOL           *VarConin;
2828   UINTN                              DevicePathSize;
2829 
2830 
2831   Index = 0;
2832   Status = EFI_SUCCESS;
2833   DevicePathSize = 0;
2834   VarConout = BdsLibGetVariableAndSize (
2835                 L"ConOut",
2836                 &gEfiGlobalVariableGuid,
2837                 &DevicePathSize
2838                 );
2839   VarConin = BdsLibGetVariableAndSize (
2840                L"ConIn",
2841                &gEfiGlobalVariableGuid,
2842                &DevicePathSize
2843                );
2844   if (VarConout == NULL || VarConin == NULL) {
2845     //
2846     // Have chance to connect the platform default console,
2847     // the platform default console is the minimue device group
2848     // the platform should support
2849     //
2850     while (PlatformConsole[Index].DevicePath != NULL) {
2851 
2852       //
2853       // Update the console variable with the connect type
2854       //
2855       if ((PlatformConsole[Index].ConnectType & CONSOLE_IN) == CONSOLE_IN) {
2856         BdsLibUpdateConsoleVariable (L"ConIn", PlatformConsole[Index].DevicePath, NULL);
2857       }
2858 
2859       if ((PlatformConsole[Index].ConnectType & CONSOLE_OUT) == CONSOLE_OUT) {
2860         BdsLibUpdateConsoleVariable (L"ConOut", PlatformConsole[Index].DevicePath, NULL);
2861       }
2862 
2863       if ((PlatformConsole[Index].ConnectType & STD_ERROR) == STD_ERROR) {
2864         BdsLibUpdateConsoleVariable (L"ErrOut", PlatformConsole[Index].DevicePath, NULL);
2865       }
2866 
2867       Index ++;
2868     }
2869   }
2870 
2871   //
2872   // Connect ConIn first to give keyboard time to parse hot key event.
2873   //
2874   Status = BdsLibConnectConsoleVariable (L"ConIn");
2875   if (EFI_ERROR (Status)) {
2876     return Status;
2877   }
2878 
2879   //
2880   // Make sure we have at least one active VGA, and have the right
2881   // active VGA in console variable
2882   //
2883   Status = PlatformBdsForceActiveVga ();
2884 
2885   //
2886   // It seems impossible not to have any ConOut device on platform,
2887   // so we check the status here.
2888   //
2889   Status = BdsLibConnectConsoleVariable (L"ConOut");
2890   if (EFI_ERROR (Status)) {
2891     return Status;
2892   }
2893 
2894   return EFI_SUCCESS;
2895 }
2896 
HotKeyTimerHandler(IN EFI_EVENT Event,IN VOID * Context)2897 
2898 /**
2899   Timer handler to convert the key from USB.
2900 
2901   @param  Event                    Indicates the event that invoke this function.
2902   @param  Context                  Indicates the calling context.
2903 **/
2904 VOID
2905 EFIAPI
2906 HotKeyTimerHandler (
2907   IN  EFI_EVENT                 Event,
2908   IN  VOID                      *Context
2909   )
2910 {
2911   EFI_STATUS                    Status;
2912   EFI_INPUT_KEY                 Key;
2913 
2914   Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
2915   if (EFI_ERROR (Status)) {
2916     return;
2917   }
2918 
2919   switch(Key.ScanCode) {
2920   case SCAN_F2:
2921     gHotKey = 0;
2922     mHotKeyPressed = TRUE;
2923     break;
2924 
2925   case SCAN_F5:
2926     gHotKey = FRONT_PAGE_KEY_DEVICE_MANAGER;
2927     mHotKeyPressed = TRUE;
2928     break;
2929 
2930   case SCAN_F7:
2931     gHotKey = FRONT_PAGE_KEY_BOOT_MANAGER;
2932     mHotKeyPressed = TRUE;
2933     break;
2934 
2935   case SCAN_F9:
2936     gHotKey = FRONT_PAGE_KEY_BOOT_MAINTAIN;
2937     mHotKeyPressed = TRUE;
2938     break;
2939   }
2940 
2941   if (mHotKeyPressed) {
2942     gBS->SetTimer (
2943            mHotKeyTimerEvent,
2944            TimerCancel,
2945            0
2946            );
2947     gBS->CloseEvent (mHotKeyTimerEvent);
2948     mHotKeyTimerEvent = NULL;
2949   }
2950 
2951   return;
2952 }
2953 
2954 
HitHotkeyEvent(IN EFI_EVENT Event,IN VOID * Context)2955 /**
2956   Callback function for SimpleTextInEx protocol install events
2957 
2958   @param Event           the event that is signaled.
2959   @param Context         not used here.
2960 
2961 **/
2962 VOID
2963 EFIAPI
2964 HitHotkeyEvent (
2965   IN EFI_EVENT    Event,
2966   IN VOID         *Context
2967   )
2968 {
2969   EFI_STATUS                         Status;
2970 
2971   Status = gBS->CloseEvent(mHitHotkeyEvent);
2972   if (EFI_ERROR (Status)) {
2973     return;
2974   }
2975   Status = gBS->CreateEvent (
2976                   EVT_TIMER | EVT_NOTIFY_SIGNAL,
2977                   TPL_NOTIFY,
2978                   HotKeyTimerHandler,
2979                   NULL,
2980                   &mHotKeyTimerEvent
2981                   );
2982   if (EFI_ERROR (Status)) {
2983     return;
2984   }
2985   Status = gBS->SetTimer (
2986                   mHotKeyTimerEvent,
2987                   TimerPeriodic,
2988                   KEYBOARD_TIMER_INTERVAL
2989                   );
2990   if (EFI_ERROR (Status)) {
2991     return;
2992   }
2993 
2994   return;
2995 }
2996 
2997 
2998 VOID
2999 EFIAPI
3000 PlatformBdsInitHotKeyEvent (
3001   VOID
3002   )
3003 {
3004   EFI_STATUS      Status;
3005 
3006   //
3007   // Register Protocol notify for Hotkey service
3008   //
3009   Status = gBS->CreateEvent (
3010                   EVT_NOTIFY_SIGNAL,
3011                   TPL_CALLBACK,
3012                   HitHotkeyEvent,
3013                   NULL,
3014                   &mHitHotkeyEvent
3015                   );
3016   ASSERT_EFI_ERROR (Status);
3017 
3018   //
3019   // Register for protocol notifications on this event
3020   //
3021   Status = gBS->RegisterProtocolNotify (
3022                   &gEfiSimpleTextInputExProtocolGuid,
3023                   mHitHotkeyEvent,
3024                   &mHitHotkeyRegistration
3025                   );
3026   ASSERT_EFI_ERROR (Status);
3027 }
3028