15c08e1173703234cc2913757f237ee916087498aklu/** @file
2128efbbcc2e3e8d4ee3c269563a5e2ee461dc3e3darylm  This module produce main entry for BDS phase - BdsEntry.
35c08e1173703234cc2913757f237ee916087498aklu  When this module was dispatched by DxeCore, gEfiBdsArchProtocolGuid will be installed
45c08e1173703234cc2913757f237ee916087498aklu  which contains interface of BdsEntry.
55c08e1173703234cc2913757f237ee916087498aklu  After DxeCore finish DXE phase, gEfiBdsArchProtocolGuid->BdsEntry will be invoked
65c08e1173703234cc2913757f237ee916087498aklu  to enter BDS phase.
75c08e1173703234cc2913757f237ee916087498aklu
869fc8f080e07ea026e8fbb8610cfb89c099d6db2Ruiyu NiCopyright (c) 2004 - 2014, Intel Corporation. All rights reserved.<BR>
9180a5a35cb49699bd249dee19e41cee34c856a58hhtianThis program and the accompanying materials
105c08e1173703234cc2913757f237ee916087498akluare licensed and made available under the terms and conditions of the BSD License
115c08e1173703234cc2913757f237ee916087498akluwhich accompanies this distribution.  The full text of the license may be found at
125c08e1173703234cc2913757f237ee916087498akluhttp://opensource.org/licenses/bsd-license.php
135c08e1173703234cc2913757f237ee916087498aklu
145c08e1173703234cc2913757f237ee916087498akluTHE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
155c08e1173703234cc2913757f237ee916087498akluWITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
165c08e1173703234cc2913757f237ee916087498aklu
175c08e1173703234cc2913757f237ee916087498aklu**/
185c08e1173703234cc2913757f237ee916087498aklu
195c08e1173703234cc2913757f237ee916087498aklu#include "Bds.h"
205c08e1173703234cc2913757f237ee916087498aklu#include "Language.h"
215c08e1173703234cc2913757f237ee916087498aklu#include "FrontPage.h"
225c08e1173703234cc2913757f237ee916087498aklu#include "Hotkey.h"
235c08e1173703234cc2913757f237ee916087498aklu#include "HwErrRecSupport.h"
245c08e1173703234cc2913757f237ee916087498aklu
255c08e1173703234cc2913757f237ee916087498aklu///
265c08e1173703234cc2913757f237ee916087498aklu/// BDS arch protocol instance initial value.
275c08e1173703234cc2913757f237ee916087498aklu///
285c08e1173703234cc2913757f237ee916087498aklu/// Note: Current BDS not directly get the BootMode, DefaultBoot,
295c08e1173703234cc2913757f237ee916087498aklu/// TimeoutDefault, MemoryTestLevel value from the BDS arch protocol.
30128efbbcc2e3e8d4ee3c269563a5e2ee461dc3e3darylm/// Please refer to the library useage of BdsLibGetBootMode, BdsLibGetTimeout
315c08e1173703234cc2913757f237ee916087498aklu/// and PlatformBdsDiagnostics in BdsPlatform.c
325c08e1173703234cc2913757f237ee916087498aklu///
33f7cdf5cdd38d0b5740046c26c7ca22f3d19ecb41mdkinneyEFI_HANDLE  gBdsHandle = NULL;
34f7cdf5cdd38d0b5740046c26c7ca22f3d19ecb41mdkinney
35f7cdf5cdd38d0b5740046c26c7ca22f3d19ecb41mdkinneyEFI_BDS_ARCH_PROTOCOL  gBds = {
36f7cdf5cdd38d0b5740046c26c7ca22f3d19ecb41mdkinney  BdsEntry
375c08e1173703234cc2913757f237ee916087498aklu};
385c08e1173703234cc2913757f237ee916087498aklu
395c08e1173703234cc2913757f237ee916087498akluUINT16                          *mBootNext = NULL;
405c08e1173703234cc2913757f237ee916087498aklu
41ff8438477f2dcea28149514de25368ac0b2c02eeniruiyu///
42ff8438477f2dcea28149514de25368ac0b2c02eeniruiyu/// The read-only variables defined in UEFI Spec.
43ff8438477f2dcea28149514de25368ac0b2c02eeniruiyu///
44ff8438477f2dcea28149514de25368ac0b2c02eeniruiyuCHAR16  *mReadOnlyVariables[] = {
45ff8438477f2dcea28149514de25368ac0b2c02eeniruiyu  L"PlatformLangCodes",
46ff8438477f2dcea28149514de25368ac0b2c02eeniruiyu  L"LangCodes",
47ff8438477f2dcea28149514de25368ac0b2c02eeniruiyu  L"BootOptionSupport",
48ff8438477f2dcea28149514de25368ac0b2c02eeniruiyu  L"HwErrRecSupport",
49ff8438477f2dcea28149514de25368ac0b2c02eeniruiyu  L"OsIndicationsSupported"
50ff8438477f2dcea28149514de25368ac0b2c02eeniruiyu  };
51ff8438477f2dcea28149514de25368ac0b2c02eeniruiyu
525c08e1173703234cc2913757f237ee916087498aklu/**
535c08e1173703234cc2913757f237ee916087498aklu
545c08e1173703234cc2913757f237ee916087498aklu  Install Boot Device Selection Protocol
555c08e1173703234cc2913757f237ee916087498aklu
565c08e1173703234cc2913757f237ee916087498aklu  @param ImageHandle     The image handle.
575c08e1173703234cc2913757f237ee916087498aklu  @param SystemTable     The system table.
585c08e1173703234cc2913757f237ee916087498aklu
595c08e1173703234cc2913757f237ee916087498aklu  @retval  EFI_SUCEESS  BDS has finished initializing.
605c08e1173703234cc2913757f237ee916087498aklu                        Return the dispatcher and recall BDS.Entry
615c08e1173703234cc2913757f237ee916087498aklu  @retval  Other        Return status from AllocatePool() or gBS->InstallProtocolInterface
625c08e1173703234cc2913757f237ee916087498aklu
635c08e1173703234cc2913757f237ee916087498aklu**/
645c08e1173703234cc2913757f237ee916087498akluEFI_STATUS
655c08e1173703234cc2913757f237ee916087498akluEFIAPI
665c08e1173703234cc2913757f237ee916087498akluBdsInitialize (
675c08e1173703234cc2913757f237ee916087498aklu  IN EFI_HANDLE                            ImageHandle,
685c08e1173703234cc2913757f237ee916087498aklu  IN EFI_SYSTEM_TABLE                      *SystemTable
695c08e1173703234cc2913757f237ee916087498aklu  )
705c08e1173703234cc2913757f237ee916087498aklu{
715c08e1173703234cc2913757f237ee916087498aklu  EFI_STATUS  Status;
725c08e1173703234cc2913757f237ee916087498aklu
735c08e1173703234cc2913757f237ee916087498aklu  //
745c08e1173703234cc2913757f237ee916087498aklu  // Install protocol interface
755c08e1173703234cc2913757f237ee916087498aklu  //
76f7cdf5cdd38d0b5740046c26c7ca22f3d19ecb41mdkinney  Status = gBS->InstallMultipleProtocolInterfaces (
77f7cdf5cdd38d0b5740046c26c7ca22f3d19ecb41mdkinney                  &gBdsHandle,
78f7cdf5cdd38d0b5740046c26c7ca22f3d19ecb41mdkinney                  &gEfiBdsArchProtocolGuid, &gBds,
79f7cdf5cdd38d0b5740046c26c7ca22f3d19ecb41mdkinney                  NULL
805c08e1173703234cc2913757f237ee916087498aklu                  );
815c08e1173703234cc2913757f237ee916087498aklu  ASSERT_EFI_ERROR (Status);
825c08e1173703234cc2913757f237ee916087498aklu
835c08e1173703234cc2913757f237ee916087498aklu  return Status;
845c08e1173703234cc2913757f237ee916087498aklu}
855c08e1173703234cc2913757f237ee916087498aklu
865676ccca070b261ff70e93bc32b5f7496c1b8c83czhang
875676ccca070b261ff70e93bc32b5f7496c1b8c83czhang/**
885676ccca070b261ff70e93bc32b5f7496c1b8c83czhang  An empty function to pass error checking of CreateEventEx ().
895676ccca070b261ff70e93bc32b5f7496c1b8c83czhang
905676ccca070b261ff70e93bc32b5f7496c1b8c83czhang  @param  Event                 Event whose notification function is being invoked.
915676ccca070b261ff70e93bc32b5f7496c1b8c83czhang  @param  Context               Pointer to the notification function's context,
925676ccca070b261ff70e93bc32b5f7496c1b8c83czhang                                which is implementation-dependent.
935676ccca070b261ff70e93bc32b5f7496c1b8c83czhang
945676ccca070b261ff70e93bc32b5f7496c1b8c83czhang**/
955676ccca070b261ff70e93bc32b5f7496c1b8c83czhangVOID
965676ccca070b261ff70e93bc32b5f7496c1b8c83czhangEFIAPI
975676ccca070b261ff70e93bc32b5f7496c1b8c83czhangBdsEmptyCallbackFunction (
985676ccca070b261ff70e93bc32b5f7496c1b8c83czhang  IN EFI_EVENT                Event,
995676ccca070b261ff70e93bc32b5f7496c1b8c83czhang  IN VOID                     *Context
1005676ccca070b261ff70e93bc32b5f7496c1b8c83czhang  )
1015676ccca070b261ff70e93bc32b5f7496c1b8c83czhang{
1025676ccca070b261ff70e93bc32b5f7496c1b8c83czhang}
1035676ccca070b261ff70e93bc32b5f7496c1b8c83czhang
1045c08e1173703234cc2913757f237ee916087498aklu/**
1055c08e1173703234cc2913757f237ee916087498aklu
1065c08e1173703234cc2913757f237ee916087498aklu  This function attempts to boot for the boot order specified
1075c08e1173703234cc2913757f237ee916087498aklu  by platform policy.
1085c08e1173703234cc2913757f237ee916087498aklu
1095c08e1173703234cc2913757f237ee916087498aklu**/
1105c08e1173703234cc2913757f237ee916087498akluVOID
1115c08e1173703234cc2913757f237ee916087498akluBdsBootDeviceSelect (
1125c08e1173703234cc2913757f237ee916087498aklu  VOID
1135c08e1173703234cc2913757f237ee916087498aklu  )
1145c08e1173703234cc2913757f237ee916087498aklu{
1155c08e1173703234cc2913757f237ee916087498aklu  EFI_STATUS        Status;
1165c08e1173703234cc2913757f237ee916087498aklu  LIST_ENTRY        *Link;
1175c08e1173703234cc2913757f237ee916087498aklu  BDS_COMMON_OPTION *BootOption;
1185c08e1173703234cc2913757f237ee916087498aklu  UINTN             ExitDataSize;
1195c08e1173703234cc2913757f237ee916087498aklu  CHAR16            *ExitData;
1205c08e1173703234cc2913757f237ee916087498aklu  UINT16            Timeout;
1215c08e1173703234cc2913757f237ee916087498aklu  LIST_ENTRY        BootLists;
1225c08e1173703234cc2913757f237ee916087498aklu  CHAR16            Buffer[20];
1235c08e1173703234cc2913757f237ee916087498aklu  BOOLEAN           BootNextExist;
1245c08e1173703234cc2913757f237ee916087498aklu  LIST_ENTRY        *LinkBootNext;
1255676ccca070b261ff70e93bc32b5f7496c1b8c83czhang  EFI_EVENT         ConnectConInEvent;
1265c08e1173703234cc2913757f237ee916087498aklu
1275c08e1173703234cc2913757f237ee916087498aklu  //
1285c08e1173703234cc2913757f237ee916087498aklu  // Got the latest boot option
1295c08e1173703234cc2913757f237ee916087498aklu  //
1305c08e1173703234cc2913757f237ee916087498aklu  BootNextExist = FALSE;
1315c08e1173703234cc2913757f237ee916087498aklu  LinkBootNext  = NULL;
1325676ccca070b261ff70e93bc32b5f7496c1b8c83czhang  ConnectConInEvent = NULL;
1335c08e1173703234cc2913757f237ee916087498aklu  InitializeListHead (&BootLists);
1345c08e1173703234cc2913757f237ee916087498aklu
1355c08e1173703234cc2913757f237ee916087498aklu  //
1365c08e1173703234cc2913757f237ee916087498aklu  // First check the boot next option
1375c08e1173703234cc2913757f237ee916087498aklu  //
1385c08e1173703234cc2913757f237ee916087498aklu  ZeroMem (Buffer, sizeof (Buffer));
1395c08e1173703234cc2913757f237ee916087498aklu
1405676ccca070b261ff70e93bc32b5f7496c1b8c83czhang  //
1415676ccca070b261ff70e93bc32b5f7496c1b8c83czhang  // Create Event to signal ConIn connection request
1425676ccca070b261ff70e93bc32b5f7496c1b8c83czhang  //
1435676ccca070b261ff70e93bc32b5f7496c1b8c83czhang  if (PcdGetBool (PcdConInConnectOnDemand)) {
1445676ccca070b261ff70e93bc32b5f7496c1b8c83czhang    Status = gBS->CreateEventEx (
1455676ccca070b261ff70e93bc32b5f7496c1b8c83czhang                    EVT_NOTIFY_SIGNAL,
1465676ccca070b261ff70e93bc32b5f7496c1b8c83czhang                    TPL_CALLBACK,
1475676ccca070b261ff70e93bc32b5f7496c1b8c83czhang                    BdsEmptyCallbackFunction,
1485676ccca070b261ff70e93bc32b5f7496c1b8c83czhang                    NULL,
1495676ccca070b261ff70e93bc32b5f7496c1b8c83czhang                    &gConnectConInEventGuid,
1505676ccca070b261ff70e93bc32b5f7496c1b8c83czhang                    &ConnectConInEvent
1515676ccca070b261ff70e93bc32b5f7496c1b8c83czhang                    );
1525676ccca070b261ff70e93bc32b5f7496c1b8c83czhang    if (EFI_ERROR(Status)) {
1535676ccca070b261ff70e93bc32b5f7496c1b8c83czhang      ConnectConInEvent = NULL;
1545676ccca070b261ff70e93bc32b5f7496c1b8c83czhang    }
1555676ccca070b261ff70e93bc32b5f7496c1b8c83czhang  }
1565676ccca070b261ff70e93bc32b5f7496c1b8c83czhang
1575c08e1173703234cc2913757f237ee916087498aklu  if (mBootNext != NULL) {
1585c08e1173703234cc2913757f237ee916087498aklu    //
1595c08e1173703234cc2913757f237ee916087498aklu    // Indicate we have the boot next variable, so this time
1605c08e1173703234cc2913757f237ee916087498aklu    // boot will always have this boot option
1615c08e1173703234cc2913757f237ee916087498aklu    //
1625c08e1173703234cc2913757f237ee916087498aklu    BootNextExist = TRUE;
1635c08e1173703234cc2913757f237ee916087498aklu
1645c08e1173703234cc2913757f237ee916087498aklu    //
1655c08e1173703234cc2913757f237ee916087498aklu    // Clear the this variable so it's only exist in this time boot
1665c08e1173703234cc2913757f237ee916087498aklu    //
16769fc8f080e07ea026e8fbb8610cfb89c099d6db2Ruiyu Ni    Status = gRT->SetVariable (
16869fc8f080e07ea026e8fbb8610cfb89c099d6db2Ruiyu Ni                    L"BootNext",
16969fc8f080e07ea026e8fbb8610cfb89c099d6db2Ruiyu Ni                    &gEfiGlobalVariableGuid,
17069fc8f080e07ea026e8fbb8610cfb89c099d6db2Ruiyu Ni                    EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
17169fc8f080e07ea026e8fbb8610cfb89c099d6db2Ruiyu Ni                    0,
17269fc8f080e07ea026e8fbb8610cfb89c099d6db2Ruiyu Ni                    NULL
17369fc8f080e07ea026e8fbb8610cfb89c099d6db2Ruiyu Ni                    );
17469fc8f080e07ea026e8fbb8610cfb89c099d6db2Ruiyu Ni    //
17569fc8f080e07ea026e8fbb8610cfb89c099d6db2Ruiyu Ni    // Deleting variable with current variable implementation shouldn't fail.
17669fc8f080e07ea026e8fbb8610cfb89c099d6db2Ruiyu Ni    //
17769fc8f080e07ea026e8fbb8610cfb89c099d6db2Ruiyu Ni    ASSERT_EFI_ERROR (Status);
1785c08e1173703234cc2913757f237ee916087498aklu
1795c08e1173703234cc2913757f237ee916087498aklu    //
1805c08e1173703234cc2913757f237ee916087498aklu    // Add the boot next boot option
1815c08e1173703234cc2913757f237ee916087498aklu    //
1825c08e1173703234cc2913757f237ee916087498aklu    UnicodeSPrint (Buffer, sizeof (Buffer), L"Boot%04x", *mBootNext);
1835c08e1173703234cc2913757f237ee916087498aklu    BootOption = BdsLibVariableToOption (&BootLists, Buffer);
184128efbbcc2e3e8d4ee3c269563a5e2ee461dc3e3darylm
1855c08e1173703234cc2913757f237ee916087498aklu    //
1865c08e1173703234cc2913757f237ee916087498aklu    // If fail to get boot option from variable, just return and do nothing.
1875c08e1173703234cc2913757f237ee916087498aklu    //
1885c08e1173703234cc2913757f237ee916087498aklu    if (BootOption == NULL) {
1895c08e1173703234cc2913757f237ee916087498aklu      return;
1905c08e1173703234cc2913757f237ee916087498aklu    }
191128efbbcc2e3e8d4ee3c269563a5e2ee461dc3e3darylm
1925c08e1173703234cc2913757f237ee916087498aklu    BootOption->BootCurrent = *mBootNext;
1935c08e1173703234cc2913757f237ee916087498aklu  }
1945c08e1173703234cc2913757f237ee916087498aklu  //
1955c08e1173703234cc2913757f237ee916087498aklu  // Parse the boot order to get boot option
1965c08e1173703234cc2913757f237ee916087498aklu  //
1975c08e1173703234cc2913757f237ee916087498aklu  BdsLibBuildOptionFromVar (&BootLists, L"BootOrder");
198d860010877dd3229fe111d7d4e8f61b8a6b45b83niruiyu
199d860010877dd3229fe111d7d4e8f61b8a6b45b83niruiyu  //
200d860010877dd3229fe111d7d4e8f61b8a6b45b83niruiyu  // When we didn't have chance to build boot option variables in the first
201d860010877dd3229fe111d7d4e8f61b8a6b45b83niruiyu  // full configuration boot (e.g.: Reset in the first page or in Device Manager),
202d860010877dd3229fe111d7d4e8f61b8a6b45b83niruiyu  // we have no boot options in the following mini configuration boot.
203d860010877dd3229fe111d7d4e8f61b8a6b45b83niruiyu  // Give the last chance to enumerate the boot options.
204d860010877dd3229fe111d7d4e8f61b8a6b45b83niruiyu  //
205d860010877dd3229fe111d7d4e8f61b8a6b45b83niruiyu  if (IsListEmpty (&BootLists)) {
206d860010877dd3229fe111d7d4e8f61b8a6b45b83niruiyu    BdsLibEnumerateAllBootOption (&BootLists);
207d860010877dd3229fe111d7d4e8f61b8a6b45b83niruiyu  }
208d860010877dd3229fe111d7d4e8f61b8a6b45b83niruiyu
2095c08e1173703234cc2913757f237ee916087498aklu  Link = BootLists.ForwardLink;
2105c08e1173703234cc2913757f237ee916087498aklu
2115c08e1173703234cc2913757f237ee916087498aklu  //
2125c08e1173703234cc2913757f237ee916087498aklu  // Parameter check, make sure the loop will be valid
2135c08e1173703234cc2913757f237ee916087498aklu  //
2145c08e1173703234cc2913757f237ee916087498aklu  if (Link == NULL) {
2155c08e1173703234cc2913757f237ee916087498aklu    return ;
2165c08e1173703234cc2913757f237ee916087498aklu  }
2175c08e1173703234cc2913757f237ee916087498aklu  //
2185c08e1173703234cc2913757f237ee916087498aklu  // Here we make the boot in a loop, every boot success will
2195c08e1173703234cc2913757f237ee916087498aklu  // return to the front page
2205c08e1173703234cc2913757f237ee916087498aklu  //
2215c08e1173703234cc2913757f237ee916087498aklu  for (;;) {
2225c08e1173703234cc2913757f237ee916087498aklu    //
2235c08e1173703234cc2913757f237ee916087498aklu    // Check the boot option list first
2245c08e1173703234cc2913757f237ee916087498aklu    //
2255c08e1173703234cc2913757f237ee916087498aklu    if (Link == &BootLists) {
2265c08e1173703234cc2913757f237ee916087498aklu      //
2275676ccca070b261ff70e93bc32b5f7496c1b8c83czhang      // When LazyConIn enabled, signal connect ConIn event before enter UI
2285676ccca070b261ff70e93bc32b5f7496c1b8c83czhang      //
2295676ccca070b261ff70e93bc32b5f7496c1b8c83czhang      if (PcdGetBool (PcdConInConnectOnDemand) && ConnectConInEvent != NULL) {
2305676ccca070b261ff70e93bc32b5f7496c1b8c83czhang        gBS->SignalEvent (ConnectConInEvent);
2315676ccca070b261ff70e93bc32b5f7496c1b8c83czhang      }
2325676ccca070b261ff70e93bc32b5f7496c1b8c83czhang
2335676ccca070b261ff70e93bc32b5f7496c1b8c83czhang      //
2345c08e1173703234cc2913757f237ee916087498aklu      // There are two ways to enter here:
2355c08e1173703234cc2913757f237ee916087498aklu      // 1. There is no active boot option, give user chance to
2365c08e1173703234cc2913757f237ee916087498aklu      //    add new boot option
2375c08e1173703234cc2913757f237ee916087498aklu      // 2. All the active boot option processed, and there is no
2385c08e1173703234cc2913757f237ee916087498aklu      //    one is success to boot, then we back here to allow user
2395c08e1173703234cc2913757f237ee916087498aklu      //    add new active boot option
2405c08e1173703234cc2913757f237ee916087498aklu      //
2415c08e1173703234cc2913757f237ee916087498aklu      Timeout = 0xffff;
2425c08e1173703234cc2913757f237ee916087498aklu      PlatformBdsEnterFrontPage (Timeout, FALSE);
2435c08e1173703234cc2913757f237ee916087498aklu      InitializeListHead (&BootLists);
2445c08e1173703234cc2913757f237ee916087498aklu      BdsLibBuildOptionFromVar (&BootLists, L"BootOrder");
2455c08e1173703234cc2913757f237ee916087498aklu      Link = BootLists.ForwardLink;
2465c08e1173703234cc2913757f237ee916087498aklu      continue;
2475c08e1173703234cc2913757f237ee916087498aklu    }
2485c08e1173703234cc2913757f237ee916087498aklu    //
2495c08e1173703234cc2913757f237ee916087498aklu    // Get the boot option from the link list
2505c08e1173703234cc2913757f237ee916087498aklu    //
2515c08e1173703234cc2913757f237ee916087498aklu    BootOption = CR (Link, BDS_COMMON_OPTION, Link, BDS_LOAD_OPTION_SIGNATURE);
2525c08e1173703234cc2913757f237ee916087498aklu
2535c08e1173703234cc2913757f237ee916087498aklu    //
2545c08e1173703234cc2913757f237ee916087498aklu    // According to EFI Specification, if a load option is not marked
2555c08e1173703234cc2913757f237ee916087498aklu    // as LOAD_OPTION_ACTIVE, the boot manager will not automatically
2565c08e1173703234cc2913757f237ee916087498aklu    // load the option.
2575c08e1173703234cc2913757f237ee916087498aklu    //
2585c08e1173703234cc2913757f237ee916087498aklu    if (!IS_LOAD_OPTION_TYPE (BootOption->Attribute, LOAD_OPTION_ACTIVE)) {
2595c08e1173703234cc2913757f237ee916087498aklu      //
260baf46e70a58d125b30b62fa24a59dd321b283fdcgikidy      // skip the header of the link list, because it has no boot option
2615c08e1173703234cc2913757f237ee916087498aklu      //
2625c08e1173703234cc2913757f237ee916087498aklu      Link = Link->ForwardLink;
2635c08e1173703234cc2913757f237ee916087498aklu      continue;
2645c08e1173703234cc2913757f237ee916087498aklu    }
2655c08e1173703234cc2913757f237ee916087498aklu    //
2665c08e1173703234cc2913757f237ee916087498aklu    // Make sure the boot option device path connected,
2675c08e1173703234cc2913757f237ee916087498aklu    // but ignore the BBS device path
2685c08e1173703234cc2913757f237ee916087498aklu    //
2695c08e1173703234cc2913757f237ee916087498aklu    if (DevicePathType (BootOption->DevicePath) != BBS_DEVICE_PATH) {
2705c08e1173703234cc2913757f237ee916087498aklu      //
2715c08e1173703234cc2913757f237ee916087498aklu      // Notes: the internal shell can not been connected with device path
2725c08e1173703234cc2913757f237ee916087498aklu      // so we do not check the status here
2735c08e1173703234cc2913757f237ee916087498aklu      //
2745c08e1173703234cc2913757f237ee916087498aklu      BdsLibConnectDevicePath (BootOption->DevicePath);
2755c08e1173703234cc2913757f237ee916087498aklu    }
2762df686c67c7819e01a1487dd703faffef2b59dceczhang
2772df686c67c7819e01a1487dd703faffef2b59dceczhang    //
2782df686c67c7819e01a1487dd703faffef2b59dceczhang    // Restore to original mode before launching boot option.
2792df686c67c7819e01a1487dd703faffef2b59dceczhang    //
2802df686c67c7819e01a1487dd703faffef2b59dceczhang    BdsSetConsoleMode (FALSE);
2812df686c67c7819e01a1487dd703faffef2b59dceczhang
2825c08e1173703234cc2913757f237ee916087498aklu    //
2835c08e1173703234cc2913757f237ee916087498aklu    // All the driver options should have been processed since
2845c08e1173703234cc2913757f237ee916087498aklu    // now boot will be performed.
2855c08e1173703234cc2913757f237ee916087498aklu    //
2865c08e1173703234cc2913757f237ee916087498aklu    Status = BdsLibBootViaBootOption (BootOption, BootOption->DevicePath, &ExitDataSize, &ExitData);
28759b9d73e5ff2331330805756aa4a32039670d097niruiyu    if (Status != EFI_SUCCESS) {
2885c08e1173703234cc2913757f237ee916087498aklu      //
2895c08e1173703234cc2913757f237ee916087498aklu      // Call platform action to indicate the boot fail
2905c08e1173703234cc2913757f237ee916087498aklu      //
2915c08e1173703234cc2913757f237ee916087498aklu      BootOption->StatusString = GetStringById (STRING_TOKEN (STR_BOOT_FAILED));
2925c08e1173703234cc2913757f237ee916087498aklu      PlatformBdsBootFail (BootOption, Status, ExitData, ExitDataSize);
2935c08e1173703234cc2913757f237ee916087498aklu
2945c08e1173703234cc2913757f237ee916087498aklu      //
2955c08e1173703234cc2913757f237ee916087498aklu      // Check the next boot option
2965c08e1173703234cc2913757f237ee916087498aklu      //
2975c08e1173703234cc2913757f237ee916087498aklu      Link = Link->ForwardLink;
2985c08e1173703234cc2913757f237ee916087498aklu
2995c08e1173703234cc2913757f237ee916087498aklu    } else {
3005c08e1173703234cc2913757f237ee916087498aklu      //
3015c08e1173703234cc2913757f237ee916087498aklu      // Call platform action to indicate the boot success
3025c08e1173703234cc2913757f237ee916087498aklu      //
303128efbbcc2e3e8d4ee3c269563a5e2ee461dc3e3darylm      BootOption->StatusString = GetStringById (STRING_TOKEN (STR_BOOT_SUCCEEDED));
3045c08e1173703234cc2913757f237ee916087498aklu      PlatformBdsBootSuccess (BootOption);
3055c08e1173703234cc2913757f237ee916087498aklu
3065c08e1173703234cc2913757f237ee916087498aklu      //
3075c08e1173703234cc2913757f237ee916087498aklu      // Boot success, then stop process the boot order, and
3085c08e1173703234cc2913757f237ee916087498aklu      // present the boot manager menu, front page
3095c08e1173703234cc2913757f237ee916087498aklu      //
3105676ccca070b261ff70e93bc32b5f7496c1b8c83czhang
3115676ccca070b261ff70e93bc32b5f7496c1b8c83czhang      //
3125676ccca070b261ff70e93bc32b5f7496c1b8c83czhang      // When LazyConIn enabled, signal connect ConIn Event before enter UI
3135676ccca070b261ff70e93bc32b5f7496c1b8c83czhang      //
3145676ccca070b261ff70e93bc32b5f7496c1b8c83czhang      if (PcdGetBool (PcdConInConnectOnDemand) && ConnectConInEvent != NULL) {
3155676ccca070b261ff70e93bc32b5f7496c1b8c83czhang        gBS->SignalEvent (ConnectConInEvent);
3165676ccca070b261ff70e93bc32b5f7496c1b8c83czhang      }
3175676ccca070b261ff70e93bc32b5f7496c1b8c83czhang
3185c08e1173703234cc2913757f237ee916087498aklu      Timeout = 0xffff;
3195c08e1173703234cc2913757f237ee916087498aklu      PlatformBdsEnterFrontPage (Timeout, FALSE);
3205c08e1173703234cc2913757f237ee916087498aklu
3215c08e1173703234cc2913757f237ee916087498aklu      //
322baf46e70a58d125b30b62fa24a59dd321b283fdcgikidy      // Rescan the boot option list, avoid potential risk of the boot
3235c08e1173703234cc2913757f237ee916087498aklu      // option change in front page
3245c08e1173703234cc2913757f237ee916087498aklu      //
3255c08e1173703234cc2913757f237ee916087498aklu      if (BootNextExist) {
3265c08e1173703234cc2913757f237ee916087498aklu        LinkBootNext = BootLists.ForwardLink;
3275c08e1173703234cc2913757f237ee916087498aklu      }
3285c08e1173703234cc2913757f237ee916087498aklu
3295c08e1173703234cc2913757f237ee916087498aklu      InitializeListHead (&BootLists);
3305c08e1173703234cc2913757f237ee916087498aklu      if (LinkBootNext != NULL) {
3315c08e1173703234cc2913757f237ee916087498aklu        //
3325c08e1173703234cc2913757f237ee916087498aklu        // Reserve the boot next option
3335c08e1173703234cc2913757f237ee916087498aklu        //
3345c08e1173703234cc2913757f237ee916087498aklu        InsertTailList (&BootLists, LinkBootNext);
3355c08e1173703234cc2913757f237ee916087498aklu      }
3365c08e1173703234cc2913757f237ee916087498aklu
3375c08e1173703234cc2913757f237ee916087498aklu      BdsLibBuildOptionFromVar (&BootLists, L"BootOrder");
3385c08e1173703234cc2913757f237ee916087498aklu      Link = BootLists.ForwardLink;
3395c08e1173703234cc2913757f237ee916087498aklu    }
3405c08e1173703234cc2913757f237ee916087498aklu  }
3415c08e1173703234cc2913757f237ee916087498aklu
3425c08e1173703234cc2913757f237ee916087498aklu}
3435c08e1173703234cc2913757f237ee916087498aklu
3445c08e1173703234cc2913757f237ee916087498aklu/**
3457ea22852094257713c3d7f31f1c02b0433c2729fydong
3467ea22852094257713c3d7f31f1c02b0433c2729fydong  Validate input console variable data.
3477ea22852094257713c3d7f31f1c02b0433c2729fydong
3487ea22852094257713c3d7f31f1c02b0433c2729fydong  If found the device path is not a valid device path, remove the variable.
3497ea22852094257713c3d7f31f1c02b0433c2729fydong
3507ea22852094257713c3d7f31f1c02b0433c2729fydong  @param VariableName             Input console variable name.
3517ea22852094257713c3d7f31f1c02b0433c2729fydong
3527ea22852094257713c3d7f31f1c02b0433c2729fydong**/
3537ea22852094257713c3d7f31f1c02b0433c2729fydongVOID
3547ea22852094257713c3d7f31f1c02b0433c2729fydongBdsFormalizeConsoleVariable (
3557ea22852094257713c3d7f31f1c02b0433c2729fydong  IN  CHAR16          *VariableName
3567ea22852094257713c3d7f31f1c02b0433c2729fydong  )
3577ea22852094257713c3d7f31f1c02b0433c2729fydong{
3587ea22852094257713c3d7f31f1c02b0433c2729fydong  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
3597ea22852094257713c3d7f31f1c02b0433c2729fydong  UINTN                     VariableSize;
3607ea22852094257713c3d7f31f1c02b0433c2729fydong  EFI_STATUS                Status;
3617ea22852094257713c3d7f31f1c02b0433c2729fydong
3627ea22852094257713c3d7f31f1c02b0433c2729fydong  DevicePath = BdsLibGetVariableAndSize (
3637ea22852094257713c3d7f31f1c02b0433c2729fydong                      VariableName,
3647ea22852094257713c3d7f31f1c02b0433c2729fydong                      &gEfiGlobalVariableGuid,
3657ea22852094257713c3d7f31f1c02b0433c2729fydong                      &VariableSize
3667ea22852094257713c3d7f31f1c02b0433c2729fydong                      );
36798b241d634c652bb615e1fd33cc2e4bb8efc7216niruiyu  if ((DevicePath != NULL) && !IsDevicePathValid (DevicePath, VariableSize)) {
3687ea22852094257713c3d7f31f1c02b0433c2729fydong    Status = gRT->SetVariable (
3697ea22852094257713c3d7f31f1c02b0433c2729fydong                    VariableName,
3707ea22852094257713c3d7f31f1c02b0433c2729fydong                    &gEfiGlobalVariableGuid,
3717ea22852094257713c3d7f31f1c02b0433c2729fydong                    EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
3727ea22852094257713c3d7f31f1c02b0433c2729fydong                    0,
3737ea22852094257713c3d7f31f1c02b0433c2729fydong                    NULL
3747ea22852094257713c3d7f31f1c02b0433c2729fydong                    );
37569fc8f080e07ea026e8fbb8610cfb89c099d6db2Ruiyu Ni    //
37669fc8f080e07ea026e8fbb8610cfb89c099d6db2Ruiyu Ni    // Deleting variable with current variable implementation shouldn't fail.
37769fc8f080e07ea026e8fbb8610cfb89c099d6db2Ruiyu Ni    //
3787ea22852094257713c3d7f31f1c02b0433c2729fydong    ASSERT_EFI_ERROR (Status);
3797ea22852094257713c3d7f31f1c02b0433c2729fydong  }
3807ea22852094257713c3d7f31f1c02b0433c2729fydong}
3817ea22852094257713c3d7f31f1c02b0433c2729fydong
3827ea22852094257713c3d7f31f1c02b0433c2729fydong/**
3837ea22852094257713c3d7f31f1c02b0433c2729fydong
38418cf3950226cb7e279f19978ea441ce6639f7bb3czhang  Formalize Bds global variables.
3857ea22852094257713c3d7f31f1c02b0433c2729fydong
38618cf3950226cb7e279f19978ea441ce6639f7bb3czhang 1. For ConIn/ConOut/ConErr, if found the device path is not a valid device path, remove the variable.
38718cf3950226cb7e279f19978ea441ce6639f7bb3czhang 2. For OsIndicationsSupported, Create a BS/RT/UINT64 variable to report caps
38818cf3950226cb7e279f19978ea441ce6639f7bb3czhang 3. Delete OsIndications variable if it is not NV/BS/RT UINT64
38918cf3950226cb7e279f19978ea441ce6639f7bb3czhang Item 3 is used to solve case when OS corrupts OsIndications. Here simply delete this NV variable.
39018cf3950226cb7e279f19978ea441ce6639f7bb3czhang
3917ea22852094257713c3d7f31f1c02b0433c2729fydong**/
3927ea22852094257713c3d7f31f1c02b0433c2729fydongVOID
3937ea22852094257713c3d7f31f1c02b0433c2729fydongBdsFormalizeEfiGlobalVariable (
3947ea22852094257713c3d7f31f1c02b0433c2729fydong  VOID
3957ea22852094257713c3d7f31f1c02b0433c2729fydong  )
3967ea22852094257713c3d7f31f1c02b0433c2729fydong{
39718cf3950226cb7e279f19978ea441ce6639f7bb3czhang  EFI_STATUS Status;
39818cf3950226cb7e279f19978ea441ce6639f7bb3czhang  UINT64     OsIndicationSupport;
39918cf3950226cb7e279f19978ea441ce6639f7bb3czhang  UINT64     OsIndication;
40018cf3950226cb7e279f19978ea441ce6639f7bb3czhang  UINTN      DataSize;
40118cf3950226cb7e279f19978ea441ce6639f7bb3czhang  UINT32     Attributes;
40218cf3950226cb7e279f19978ea441ce6639f7bb3czhang
4037ea22852094257713c3d7f31f1c02b0433c2729fydong  //
4047ea22852094257713c3d7f31f1c02b0433c2729fydong  // Validate Console variable.
4057ea22852094257713c3d7f31f1c02b0433c2729fydong  //
4067ea22852094257713c3d7f31f1c02b0433c2729fydong  BdsFormalizeConsoleVariable (L"ConIn");
4077ea22852094257713c3d7f31f1c02b0433c2729fydong  BdsFormalizeConsoleVariable (L"ConOut");
4087ea22852094257713c3d7f31f1c02b0433c2729fydong  BdsFormalizeConsoleVariable (L"ErrOut");
40918cf3950226cb7e279f19978ea441ce6639f7bb3czhang
41018cf3950226cb7e279f19978ea441ce6639f7bb3czhang  //
41118cf3950226cb7e279f19978ea441ce6639f7bb3czhang  // OS indicater support variable
41218cf3950226cb7e279f19978ea441ce6639f7bb3czhang  //
413566771b0a70a4ec637420c4b96a1415348bf2f12czhang  OsIndicationSupport = EFI_OS_INDICATIONS_BOOT_TO_FW_UI \
414566771b0a70a4ec637420c4b96a1415348bf2f12czhang                      | EFI_OS_INDICATIONS_FMP_CAPSULE_SUPPORTED;
415566771b0a70a4ec637420c4b96a1415348bf2f12czhang
41669fc8f080e07ea026e8fbb8610cfb89c099d6db2Ruiyu Ni  BdsDxeSetVariableAndReportStatusCodeOnError (
41769fc8f080e07ea026e8fbb8610cfb89c099d6db2Ruiyu Ni    L"OsIndicationsSupported",
41869fc8f080e07ea026e8fbb8610cfb89c099d6db2Ruiyu Ni    &gEfiGlobalVariableGuid,
41969fc8f080e07ea026e8fbb8610cfb89c099d6db2Ruiyu Ni    EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
42069fc8f080e07ea026e8fbb8610cfb89c099d6db2Ruiyu Ni    sizeof(UINT64),
42169fc8f080e07ea026e8fbb8610cfb89c099d6db2Ruiyu Ni    &OsIndicationSupport
42269fc8f080e07ea026e8fbb8610cfb89c099d6db2Ruiyu Ni    );
42318cf3950226cb7e279f19978ea441ce6639f7bb3czhang
42418cf3950226cb7e279f19978ea441ce6639f7bb3czhang  //
42518cf3950226cb7e279f19978ea441ce6639f7bb3czhang  // If OsIndications is invalid, remove it.
42618cf3950226cb7e279f19978ea441ce6639f7bb3czhang  // Invalid case
42718cf3950226cb7e279f19978ea441ce6639f7bb3czhang  //   1. Data size != UINT64
42818cf3950226cb7e279f19978ea441ce6639f7bb3czhang  //   2. OsIndication value inconsistence
42918cf3950226cb7e279f19978ea441ce6639f7bb3czhang  //   3. OsIndication attribute inconsistence
43018cf3950226cb7e279f19978ea441ce6639f7bb3czhang  //
43118cf3950226cb7e279f19978ea441ce6639f7bb3czhang  OsIndication = 0;
43218cf3950226cb7e279f19978ea441ce6639f7bb3czhang  Attributes = 0;
43318cf3950226cb7e279f19978ea441ce6639f7bb3czhang  DataSize = sizeof(UINT64);
43418cf3950226cb7e279f19978ea441ce6639f7bb3czhang  Status = gRT->GetVariable (
43518cf3950226cb7e279f19978ea441ce6639f7bb3czhang                  L"OsIndications",
43618cf3950226cb7e279f19978ea441ce6639f7bb3czhang                  &gEfiGlobalVariableGuid,
43718cf3950226cb7e279f19978ea441ce6639f7bb3czhang                  &Attributes,
43818cf3950226cb7e279f19978ea441ce6639f7bb3czhang                  &DataSize,
43918cf3950226cb7e279f19978ea441ce6639f7bb3czhang                  &OsIndication
44018cf3950226cb7e279f19978ea441ce6639f7bb3czhang                  );
44118cf3950226cb7e279f19978ea441ce6639f7bb3czhang
44218cf3950226cb7e279f19978ea441ce6639f7bb3czhang  if (!EFI_ERROR(Status)) {
44318cf3950226cb7e279f19978ea441ce6639f7bb3czhang    if (DataSize != sizeof(UINT64) ||
44418cf3950226cb7e279f19978ea441ce6639f7bb3czhang        (OsIndication & ~OsIndicationSupport) != 0 ||
44518cf3950226cb7e279f19978ea441ce6639f7bb3czhang        Attributes != (EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE)){
44618cf3950226cb7e279f19978ea441ce6639f7bb3czhang
44718cf3950226cb7e279f19978ea441ce6639f7bb3czhang      DEBUG ((EFI_D_ERROR, "Unformalized OsIndications variable exists. Delete it\n"));
44818cf3950226cb7e279f19978ea441ce6639f7bb3czhang      Status = gRT->SetVariable (
44918cf3950226cb7e279f19978ea441ce6639f7bb3czhang                      L"OsIndications",
45018cf3950226cb7e279f19978ea441ce6639f7bb3czhang                      &gEfiGlobalVariableGuid,
45118cf3950226cb7e279f19978ea441ce6639f7bb3czhang                      0,
45269fc8f080e07ea026e8fbb8610cfb89c099d6db2Ruiyu Ni                      0,
45369fc8f080e07ea026e8fbb8610cfb89c099d6db2Ruiyu Ni                      NULL
45418cf3950226cb7e279f19978ea441ce6639f7bb3czhang                      );
45569fc8f080e07ea026e8fbb8610cfb89c099d6db2Ruiyu Ni      //
45669fc8f080e07ea026e8fbb8610cfb89c099d6db2Ruiyu Ni      // Deleting variable with current variable implementation shouldn't fail.
45769fc8f080e07ea026e8fbb8610cfb89c099d6db2Ruiyu Ni      //
45818cf3950226cb7e279f19978ea441ce6639f7bb3czhang      ASSERT_EFI_ERROR (Status);
45918cf3950226cb7e279f19978ea441ce6639f7bb3czhang    }
46018cf3950226cb7e279f19978ea441ce6639f7bb3czhang  }
46118cf3950226cb7e279f19978ea441ce6639f7bb3czhang
4627ea22852094257713c3d7f31f1c02b0433c2729fydong}
4637ea22852094257713c3d7f31f1c02b0433c2729fydong
4647ea22852094257713c3d7f31f1c02b0433c2729fydong/**
4655c08e1173703234cc2913757f237ee916087498aklu
466f6c07313d1f7317c328e9ef80cfb272beec0a249lzeng  Allocate a block of memory that will contain performance data to OS.
467f6c07313d1f7317c328e9ef80cfb272beec0a249lzeng
468f6c07313d1f7317c328e9ef80cfb272beec0a249lzeng**/
469f6c07313d1f7317c328e9ef80cfb272beec0a249lzengVOID
470f6c07313d1f7317c328e9ef80cfb272beec0a249lzengBdsAllocateMemoryForPerformanceData (
471f6c07313d1f7317c328e9ef80cfb272beec0a249lzeng  VOID
472f6c07313d1f7317c328e9ef80cfb272beec0a249lzeng  )
473f6c07313d1f7317c328e9ef80cfb272beec0a249lzeng{
474f6c07313d1f7317c328e9ef80cfb272beec0a249lzeng  EFI_STATUS                    Status;
475f6c07313d1f7317c328e9ef80cfb272beec0a249lzeng  EFI_PHYSICAL_ADDRESS          AcpiLowMemoryBase;
476f6c07313d1f7317c328e9ef80cfb272beec0a249lzeng  EDKII_VARIABLE_LOCK_PROTOCOL  *VariableLock;
477f6c07313d1f7317c328e9ef80cfb272beec0a249lzeng
478f6c07313d1f7317c328e9ef80cfb272beec0a249lzeng  AcpiLowMemoryBase = 0x0FFFFFFFFULL;
479f6c07313d1f7317c328e9ef80cfb272beec0a249lzeng
480f6c07313d1f7317c328e9ef80cfb272beec0a249lzeng  //
481f6c07313d1f7317c328e9ef80cfb272beec0a249lzeng  // Allocate a block of memory that will contain performance data to OS.
482f6c07313d1f7317c328e9ef80cfb272beec0a249lzeng  //
483f6c07313d1f7317c328e9ef80cfb272beec0a249lzeng  Status = gBS->AllocatePages (
484f6c07313d1f7317c328e9ef80cfb272beec0a249lzeng                  AllocateMaxAddress,
485f6c07313d1f7317c328e9ef80cfb272beec0a249lzeng                  EfiReservedMemoryType,
486f6c07313d1f7317c328e9ef80cfb272beec0a249lzeng                  EFI_SIZE_TO_PAGES (PERF_DATA_MAX_LENGTH),
487f6c07313d1f7317c328e9ef80cfb272beec0a249lzeng                  &AcpiLowMemoryBase
488f6c07313d1f7317c328e9ef80cfb272beec0a249lzeng                  );
489f6c07313d1f7317c328e9ef80cfb272beec0a249lzeng  if (!EFI_ERROR (Status)) {
490f6c07313d1f7317c328e9ef80cfb272beec0a249lzeng    //
491f6c07313d1f7317c328e9ef80cfb272beec0a249lzeng    // Save the pointer to variable for use in S3 resume.
492f6c07313d1f7317c328e9ef80cfb272beec0a249lzeng    //
49369fc8f080e07ea026e8fbb8610cfb89c099d6db2Ruiyu Ni    BdsDxeSetVariableAndReportStatusCodeOnError (
49469fc8f080e07ea026e8fbb8610cfb89c099d6db2Ruiyu Ni      L"PerfDataMemAddr",
49569fc8f080e07ea026e8fbb8610cfb89c099d6db2Ruiyu Ni      &gPerformanceProtocolGuid,
49669fc8f080e07ea026e8fbb8610cfb89c099d6db2Ruiyu Ni      EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
49769fc8f080e07ea026e8fbb8610cfb89c099d6db2Ruiyu Ni      sizeof (EFI_PHYSICAL_ADDRESS),
49869fc8f080e07ea026e8fbb8610cfb89c099d6db2Ruiyu Ni      &AcpiLowMemoryBase
49969fc8f080e07ea026e8fbb8610cfb89c099d6db2Ruiyu Ni      );
50069fc8f080e07ea026e8fbb8610cfb89c099d6db2Ruiyu Ni    if (EFI_ERROR (Status)) {
50169fc8f080e07ea026e8fbb8610cfb89c099d6db2Ruiyu Ni      DEBUG ((EFI_D_ERROR, "[Bds] PerfDataMemAddr (%08x) cannot be saved to NV storage.\n", AcpiLowMemoryBase));
50269fc8f080e07ea026e8fbb8610cfb89c099d6db2Ruiyu Ni    }
503f6c07313d1f7317c328e9ef80cfb272beec0a249lzeng    //
504f6c07313d1f7317c328e9ef80cfb272beec0a249lzeng    // Mark L"PerfDataMemAddr" variable to read-only if the Variable Lock protocol exists
50569fc8f080e07ea026e8fbb8610cfb89c099d6db2Ruiyu Ni    // Still lock it even the variable cannot be saved to prevent it's set by 3rd party code.
506f6c07313d1f7317c328e9ef80cfb272beec0a249lzeng    //
507f6c07313d1f7317c328e9ef80cfb272beec0a249lzeng    Status = gBS->LocateProtocol (&gEdkiiVariableLockProtocolGuid, NULL, (VOID **) &VariableLock);
508f6c07313d1f7317c328e9ef80cfb272beec0a249lzeng    if (!EFI_ERROR (Status)) {
509f6c07313d1f7317c328e9ef80cfb272beec0a249lzeng      Status = VariableLock->RequestToLock (VariableLock, L"PerfDataMemAddr", &gPerformanceProtocolGuid);
510f6c07313d1f7317c328e9ef80cfb272beec0a249lzeng      ASSERT_EFI_ERROR (Status);
511f6c07313d1f7317c328e9ef80cfb272beec0a249lzeng    }
512f6c07313d1f7317c328e9ef80cfb272beec0a249lzeng  }
513f6c07313d1f7317c328e9ef80cfb272beec0a249lzeng}
514f6c07313d1f7317c328e9ef80cfb272beec0a249lzeng
515f6c07313d1f7317c328e9ef80cfb272beec0a249lzeng/**
516f6c07313d1f7317c328e9ef80cfb272beec0a249lzeng
5175c08e1173703234cc2913757f237ee916087498aklu  Service routine for BdsInstance->Entry(). Devices are connected, the
5185c08e1173703234cc2913757f237ee916087498aklu  consoles are initialized, and the boot options are tried.
5195c08e1173703234cc2913757f237ee916087498aklu
5205c08e1173703234cc2913757f237ee916087498aklu  @param This             Protocol Instance structure.
5215c08e1173703234cc2913757f237ee916087498aklu
5225c08e1173703234cc2913757f237ee916087498aklu**/
5235c08e1173703234cc2913757f237ee916087498akluVOID
5245c08e1173703234cc2913757f237ee916087498akluEFIAPI
5255c08e1173703234cc2913757f237ee916087498akluBdsEntry (
5265c08e1173703234cc2913757f237ee916087498aklu  IN EFI_BDS_ARCH_PROTOCOL  *This
5275c08e1173703234cc2913757f237ee916087498aklu  )
5285c08e1173703234cc2913757f237ee916087498aklu{
5295c08e1173703234cc2913757f237ee916087498aklu  LIST_ENTRY                      DriverOptionList;
5305c08e1173703234cc2913757f237ee916087498aklu  LIST_ENTRY                      BootOptionList;
5315c08e1173703234cc2913757f237ee916087498aklu  UINTN                           BootNextSize;
5329a6b4de21d53c3acf85e1948bf0d3a5e5576172cmdkinney  CHAR16                          *FirmwareVendor;
533e1e91b73d12cb87cac0472b86a6df167db0a057flzeng  EFI_STATUS                      Status;
534e1e91b73d12cb87cac0472b86a6df167db0a057flzeng  UINT16                          BootTimeOut;
535ff8438477f2dcea28149514de25368ac0b2c02eeniruiyu  UINTN                           Index;
536ff8438477f2dcea28149514de25368ac0b2c02eeniruiyu  EDKII_VARIABLE_LOCK_PROTOCOL    *VariableLock;
5375c08e1173703234cc2913757f237ee916087498aklu
5385c08e1173703234cc2913757f237ee916087498aklu  //
5395c08e1173703234cc2913757f237ee916087498aklu  // Insert the performance probe
5405c08e1173703234cc2913757f237ee916087498aklu  //
541128efbbcc2e3e8d4ee3c269563a5e2ee461dc3e3darylm  PERF_END (NULL, "DXE", NULL, 0);
542128efbbcc2e3e8d4ee3c269563a5e2ee461dc3e3darylm  PERF_START (NULL, "BDS", NULL, 0);
5435c08e1173703234cc2913757f237ee916087498aklu
544f6c07313d1f7317c328e9ef80cfb272beec0a249lzeng  PERF_CODE (
545f6c07313d1f7317c328e9ef80cfb272beec0a249lzeng    BdsAllocateMemoryForPerformanceData ();
546f6c07313d1f7317c328e9ef80cfb272beec0a249lzeng  );
547f6c07313d1f7317c328e9ef80cfb272beec0a249lzeng
5485c08e1173703234cc2913757f237ee916087498aklu  //
5495c08e1173703234cc2913757f237ee916087498aklu  // Initialize the global system boot option and driver option
5505c08e1173703234cc2913757f237ee916087498aklu  //
5515c08e1173703234cc2913757f237ee916087498aklu  InitializeListHead (&DriverOptionList);
5525c08e1173703234cc2913757f237ee916087498aklu  InitializeListHead (&BootOptionList);
5535c08e1173703234cc2913757f237ee916087498aklu
5545c08e1173703234cc2913757f237ee916087498aklu  //
5555c08e1173703234cc2913757f237ee916087498aklu  // Initialize hotkey service
5565c08e1173703234cc2913757f237ee916087498aklu  //
5575c08e1173703234cc2913757f237ee916087498aklu  InitializeHotkeyService ();
5585c08e1173703234cc2913757f237ee916087498aklu
5595c08e1173703234cc2913757f237ee916087498aklu  //
5609a6b4de21d53c3acf85e1948bf0d3a5e5576172cmdkinney  // Fill in FirmwareVendor and FirmwareRevision from PCDs
5619a6b4de21d53c3acf85e1948bf0d3a5e5576172cmdkinney  //
5629a6b4de21d53c3acf85e1948bf0d3a5e5576172cmdkinney  FirmwareVendor = (CHAR16 *)PcdGetPtr (PcdFirmwareVendor);
5639a6b4de21d53c3acf85e1948bf0d3a5e5576172cmdkinney  gST->FirmwareVendor = AllocateRuntimeCopyPool (StrSize (FirmwareVendor), FirmwareVendor);
5649a6b4de21d53c3acf85e1948bf0d3a5e5576172cmdkinney  ASSERT (gST->FirmwareVendor != NULL);
5659a6b4de21d53c3acf85e1948bf0d3a5e5576172cmdkinney  gST->FirmwareRevision = PcdGet32 (PcdFirmwareRevision);
5669a6b4de21d53c3acf85e1948bf0d3a5e5576172cmdkinney
5679a6b4de21d53c3acf85e1948bf0d3a5e5576172cmdkinney  //
5689a6b4de21d53c3acf85e1948bf0d3a5e5576172cmdkinney  // Fixup Tasble CRC after we updated Firmware Vendor and Revision
5699a6b4de21d53c3acf85e1948bf0d3a5e5576172cmdkinney  //
570d2b9b337374b3641226f833919323f016cb83314ydong  gST->Hdr.CRC32 = 0;
5719a6b4de21d53c3acf85e1948bf0d3a5e5576172cmdkinney  gBS->CalculateCrc32 ((VOID *)gST, sizeof(EFI_SYSTEM_TABLE), &gST->Hdr.CRC32);
5729a6b4de21d53c3acf85e1948bf0d3a5e5576172cmdkinney
5739a6b4de21d53c3acf85e1948bf0d3a5e5576172cmdkinney  //
5747ea22852094257713c3d7f31f1c02b0433c2729fydong  // Validate Variable.
5757ea22852094257713c3d7f31f1c02b0433c2729fydong  //
5767ea22852094257713c3d7f31f1c02b0433c2729fydong  BdsFormalizeEfiGlobalVariable();
5777ea22852094257713c3d7f31f1c02b0433c2729fydong
5787ea22852094257713c3d7f31f1c02b0433c2729fydong  //
579ff8438477f2dcea28149514de25368ac0b2c02eeniruiyu  // Mark the read-only variables if the Variable Lock protocol exists
580ff8438477f2dcea28149514de25368ac0b2c02eeniruiyu  //
581ff8438477f2dcea28149514de25368ac0b2c02eeniruiyu  Status = gBS->LocateProtocol (&gEdkiiVariableLockProtocolGuid, NULL, (VOID **) &VariableLock);
582ff8438477f2dcea28149514de25368ac0b2c02eeniruiyu  DEBUG ((EFI_D_INFO, "[BdsDxe] Locate Variable Lock protocol - %r\n", Status));
583ff8438477f2dcea28149514de25368ac0b2c02eeniruiyu  if (!EFI_ERROR (Status)) {
584ff8438477f2dcea28149514de25368ac0b2c02eeniruiyu    for (Index = 0; Index < sizeof (mReadOnlyVariables) / sizeof (mReadOnlyVariables[0]); Index++) {
585ff8438477f2dcea28149514de25368ac0b2c02eeniruiyu      Status = VariableLock->RequestToLock (VariableLock, mReadOnlyVariables[Index], &gEfiGlobalVariableGuid);
586ff8438477f2dcea28149514de25368ac0b2c02eeniruiyu      ASSERT_EFI_ERROR (Status);
587ff8438477f2dcea28149514de25368ac0b2c02eeniruiyu    }
588ff8438477f2dcea28149514de25368ac0b2c02eeniruiyu  }
589ff8438477f2dcea28149514de25368ac0b2c02eeniruiyu
590ff8438477f2dcea28149514de25368ac0b2c02eeniruiyu  //
591cb38c322f037a9a5d2751a4c7e351b0ee7302e96li-elvin  // Report Status Code to indicate connecting drivers will happen
592cb38c322f037a9a5d2751a4c7e351b0ee7302e96li-elvin  //
593cb38c322f037a9a5d2751a4c7e351b0ee7302e96li-elvin  REPORT_STATUS_CODE (
594cb38c322f037a9a5d2751a4c7e351b0ee7302e96li-elvin    EFI_PROGRESS_CODE,
595cb38c322f037a9a5d2751a4c7e351b0ee7302e96li-elvin    (EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_DXE_BS_PC_BEGIN_CONNECTING_DRIVERS)
596cb38c322f037a9a5d2751a4c7e351b0ee7302e96li-elvin    );
597cb38c322f037a9a5d2751a4c7e351b0ee7302e96li-elvin
598a2b35995cac983b676296fcb95fde0e9121319f6klu  InitializeHwErrRecSupport();
599128efbbcc2e3e8d4ee3c269563a5e2ee461dc3e3darylm
6005c08e1173703234cc2913757f237ee916087498aklu  //
601e1e91b73d12cb87cac0472b86a6df167db0a057flzeng  // Initialize L"Timeout" EFI global variable.
602e1e91b73d12cb87cac0472b86a6df167db0a057flzeng  //
603e1e91b73d12cb87cac0472b86a6df167db0a057flzeng  BootTimeOut = PcdGet16 (PcdPlatformBootTimeOut);
604e1e91b73d12cb87cac0472b86a6df167db0a057flzeng  if (BootTimeOut != 0xFFFF) {
605e1e91b73d12cb87cac0472b86a6df167db0a057flzeng    //
606e1e91b73d12cb87cac0472b86a6df167db0a057flzeng    // If time out value equal 0xFFFF, no need set to 0xFFFF to variable area because UEFI specification
607e1e91b73d12cb87cac0472b86a6df167db0a057flzeng    // define same behavior between no value or 0xFFFF value for L"Timeout".
608e1e91b73d12cb87cac0472b86a6df167db0a057flzeng    //
60969fc8f080e07ea026e8fbb8610cfb89c099d6db2Ruiyu Ni    BdsDxeSetVariableAndReportStatusCodeOnError (
610e1e91b73d12cb87cac0472b86a6df167db0a057flzeng                    L"Timeout",
611e1e91b73d12cb87cac0472b86a6df167db0a057flzeng                    &gEfiGlobalVariableGuid,
612e1e91b73d12cb87cac0472b86a6df167db0a057flzeng                    EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
613e1e91b73d12cb87cac0472b86a6df167db0a057flzeng                    sizeof (UINT16),
614e1e91b73d12cb87cac0472b86a6df167db0a057flzeng                    &BootTimeOut
615e1e91b73d12cb87cac0472b86a6df167db0a057flzeng                    );
616e1e91b73d12cb87cac0472b86a6df167db0a057flzeng  }
617e1e91b73d12cb87cac0472b86a6df167db0a057flzeng
618e1e91b73d12cb87cac0472b86a6df167db0a057flzeng  //
6195c08e1173703234cc2913757f237ee916087498aklu  // bugbug: platform specific code
6205c08e1173703234cc2913757f237ee916087498aklu  // Initialize the platform specific string and language
6215c08e1173703234cc2913757f237ee916087498aklu  //
6225c08e1173703234cc2913757f237ee916087498aklu  InitializeStringSupport ();
6235c08e1173703234cc2913757f237ee916087498aklu  InitializeLanguage (TRUE);
6245c08e1173703234cc2913757f237ee916087498aklu  InitializeFrontPage (TRUE);
6255c08e1173703234cc2913757f237ee916087498aklu
6265c08e1173703234cc2913757f237ee916087498aklu  //
627ff8438477f2dcea28149514de25368ac0b2c02eeniruiyu  // Do the platform init, can be customized by OEM/IBV
628ff8438477f2dcea28149514de25368ac0b2c02eeniruiyu  //
629ff8438477f2dcea28149514de25368ac0b2c02eeniruiyu  PERF_START (NULL, "PlatformBds", "BDS", 0);
630ff8438477f2dcea28149514de25368ac0b2c02eeniruiyu  PlatformBdsInit ();
631ff8438477f2dcea28149514de25368ac0b2c02eeniruiyu
632ff8438477f2dcea28149514de25368ac0b2c02eeniruiyu  //
6335c08e1173703234cc2913757f237ee916087498aklu  // Set up the device list based on EFI 1.1 variables
6345c08e1173703234cc2913757f237ee916087498aklu  // process Driver#### and Load the driver's in the
6355c08e1173703234cc2913757f237ee916087498aklu  // driver option list
6365c08e1173703234cc2913757f237ee916087498aklu  //
6375c08e1173703234cc2913757f237ee916087498aklu  BdsLibBuildOptionFromVar (&DriverOptionList, L"DriverOrder");
6385c08e1173703234cc2913757f237ee916087498aklu  if (!IsListEmpty (&DriverOptionList)) {
6395c08e1173703234cc2913757f237ee916087498aklu    BdsLibLoadDrivers (&DriverOptionList);
6405c08e1173703234cc2913757f237ee916087498aklu  }
6415c08e1173703234cc2913757f237ee916087498aklu  //
6425c08e1173703234cc2913757f237ee916087498aklu  // Check if we have the boot next option
6435c08e1173703234cc2913757f237ee916087498aklu  //
6445c08e1173703234cc2913757f237ee916087498aklu  mBootNext = BdsLibGetVariableAndSize (
6455c08e1173703234cc2913757f237ee916087498aklu                L"BootNext",
6465c08e1173703234cc2913757f237ee916087498aklu                &gEfiGlobalVariableGuid,
6475c08e1173703234cc2913757f237ee916087498aklu                &BootNextSize
6485c08e1173703234cc2913757f237ee916087498aklu                );
6495c08e1173703234cc2913757f237ee916087498aklu
6505c08e1173703234cc2913757f237ee916087498aklu  //
6515c08e1173703234cc2913757f237ee916087498aklu  // Setup some platform policy here
6525c08e1173703234cc2913757f237ee916087498aklu  //
65319bf20e11acd88a02922201f97e6d64edcd16390lgao  PlatformBdsPolicyBehavior (&DriverOptionList, &BootOptionList, BdsProcessCapsules, BdsMemoryTest);
654128efbbcc2e3e8d4ee3c269563a5e2ee461dc3e3darylm  PERF_END (NULL, "PlatformBds", "BDS", 0);
6555c08e1173703234cc2913757f237ee916087498aklu
6565c08e1173703234cc2913757f237ee916087498aklu  //
6575c08e1173703234cc2913757f237ee916087498aklu  // BDS select the boot device to load OS
6585c08e1173703234cc2913757f237ee916087498aklu  //
6595c08e1173703234cc2913757f237ee916087498aklu  BdsBootDeviceSelect ();
6605c08e1173703234cc2913757f237ee916087498aklu
6615c08e1173703234cc2913757f237ee916087498aklu  //
6625c08e1173703234cc2913757f237ee916087498aklu  // Only assert here since this is the right behavior, we should never
6635c08e1173703234cc2913757f237ee916087498aklu  // return back to DxeCore.
6645c08e1173703234cc2913757f237ee916087498aklu  //
6655c08e1173703234cc2913757f237ee916087498aklu  ASSERT (FALSE);
6665c08e1173703234cc2913757f237ee916087498aklu
6675c08e1173703234cc2913757f237ee916087498aklu  return ;
6685c08e1173703234cc2913757f237ee916087498aklu}
66969fc8f080e07ea026e8fbb8610cfb89c099d6db2Ruiyu Ni
67069fc8f080e07ea026e8fbb8610cfb89c099d6db2Ruiyu Ni
67169fc8f080e07ea026e8fbb8610cfb89c099d6db2Ruiyu Ni/**
67269fc8f080e07ea026e8fbb8610cfb89c099d6db2Ruiyu Ni  Set the variable and report the error through status code upon failure.
67369fc8f080e07ea026e8fbb8610cfb89c099d6db2Ruiyu Ni
67469fc8f080e07ea026e8fbb8610cfb89c099d6db2Ruiyu Ni  @param  VariableName           A Null-terminated string that is the name of the vendor's variable.
67569fc8f080e07ea026e8fbb8610cfb89c099d6db2Ruiyu Ni                                 Each VariableName is unique for each VendorGuid. VariableName must
67669fc8f080e07ea026e8fbb8610cfb89c099d6db2Ruiyu Ni                                 contain 1 or more characters. If VariableName is an empty string,
67769fc8f080e07ea026e8fbb8610cfb89c099d6db2Ruiyu Ni                                 then EFI_INVALID_PARAMETER is returned.
67869fc8f080e07ea026e8fbb8610cfb89c099d6db2Ruiyu Ni  @param  VendorGuid             A unique identifier for the vendor.
67969fc8f080e07ea026e8fbb8610cfb89c099d6db2Ruiyu Ni  @param  Attributes             Attributes bitmask to set for the variable.
68069fc8f080e07ea026e8fbb8610cfb89c099d6db2Ruiyu Ni  @param  DataSize               The size in bytes of the Data buffer. Unless the EFI_VARIABLE_APPEND_WRITE,
68169fc8f080e07ea026e8fbb8610cfb89c099d6db2Ruiyu Ni                                 EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS, or
68269fc8f080e07ea026e8fbb8610cfb89c099d6db2Ruiyu Ni                                 EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS attribute is set, a size of zero
68369fc8f080e07ea026e8fbb8610cfb89c099d6db2Ruiyu Ni                                 causes the variable to be deleted. When the EFI_VARIABLE_APPEND_WRITE attribute is
68469fc8f080e07ea026e8fbb8610cfb89c099d6db2Ruiyu Ni                                 set, then a SetVariable() call with a DataSize of zero will not cause any change to
68569fc8f080e07ea026e8fbb8610cfb89c099d6db2Ruiyu Ni                                 the variable value (the timestamp associated with the variable may be updated however
68669fc8f080e07ea026e8fbb8610cfb89c099d6db2Ruiyu Ni                                 even if no new data value is provided,see the description of the
68769fc8f080e07ea026e8fbb8610cfb89c099d6db2Ruiyu Ni                                 EFI_VARIABLE_AUTHENTICATION_2 descriptor below. In this case the DataSize will not
68869fc8f080e07ea026e8fbb8610cfb89c099d6db2Ruiyu Ni                                 be zero since the EFI_VARIABLE_AUTHENTICATION_2 descriptor will be populated).
68969fc8f080e07ea026e8fbb8610cfb89c099d6db2Ruiyu Ni  @param  Data                   The contents for the variable.
69069fc8f080e07ea026e8fbb8610cfb89c099d6db2Ruiyu Ni
69169fc8f080e07ea026e8fbb8610cfb89c099d6db2Ruiyu Ni  @retval EFI_SUCCESS            The firmware has successfully stored the variable and its data as
69269fc8f080e07ea026e8fbb8610cfb89c099d6db2Ruiyu Ni                                 defined by the Attributes.
69369fc8f080e07ea026e8fbb8610cfb89c099d6db2Ruiyu Ni  @retval EFI_INVALID_PARAMETER  An invalid combination of attribute bits, name, and GUID was supplied, or the
69469fc8f080e07ea026e8fbb8610cfb89c099d6db2Ruiyu Ni                                 DataSize exceeds the maximum allowed.
69569fc8f080e07ea026e8fbb8610cfb89c099d6db2Ruiyu Ni  @retval EFI_INVALID_PARAMETER  VariableName is an empty string.
69669fc8f080e07ea026e8fbb8610cfb89c099d6db2Ruiyu Ni  @retval EFI_OUT_OF_RESOURCES   Not enough storage is available to hold the variable and its data.
69769fc8f080e07ea026e8fbb8610cfb89c099d6db2Ruiyu Ni  @retval EFI_DEVICE_ERROR       The variable could not be retrieved due to a hardware error.
69869fc8f080e07ea026e8fbb8610cfb89c099d6db2Ruiyu Ni  @retval EFI_WRITE_PROTECTED    The variable in question is read-only.
69969fc8f080e07ea026e8fbb8610cfb89c099d6db2Ruiyu Ni  @retval EFI_WRITE_PROTECTED    The variable in question cannot be deleted.
70069fc8f080e07ea026e8fbb8610cfb89c099d6db2Ruiyu Ni  @retval EFI_SECURITY_VIOLATION The variable could not be written due to EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS
70169fc8f080e07ea026e8fbb8610cfb89c099d6db2Ruiyu Ni                                 or EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACESS being set, but the AuthInfo
70269fc8f080e07ea026e8fbb8610cfb89c099d6db2Ruiyu Ni                                 does NOT pass the validation check carried out by the firmware.
70369fc8f080e07ea026e8fbb8610cfb89c099d6db2Ruiyu Ni
70469fc8f080e07ea026e8fbb8610cfb89c099d6db2Ruiyu Ni  @retval EFI_NOT_FOUND          The variable trying to be updated or deleted was not found.
70569fc8f080e07ea026e8fbb8610cfb89c099d6db2Ruiyu Ni**/
70669fc8f080e07ea026e8fbb8610cfb89c099d6db2Ruiyu NiEFI_STATUS
70769fc8f080e07ea026e8fbb8610cfb89c099d6db2Ruiyu NiBdsDxeSetVariableAndReportStatusCodeOnError (
70869fc8f080e07ea026e8fbb8610cfb89c099d6db2Ruiyu Ni  IN CHAR16     *VariableName,
70969fc8f080e07ea026e8fbb8610cfb89c099d6db2Ruiyu Ni  IN EFI_GUID   *VendorGuid,
71069fc8f080e07ea026e8fbb8610cfb89c099d6db2Ruiyu Ni  IN UINT32     Attributes,
71169fc8f080e07ea026e8fbb8610cfb89c099d6db2Ruiyu Ni  IN UINTN      DataSize,
71269fc8f080e07ea026e8fbb8610cfb89c099d6db2Ruiyu Ni  IN VOID       *Data
71369fc8f080e07ea026e8fbb8610cfb89c099d6db2Ruiyu Ni  )
71469fc8f080e07ea026e8fbb8610cfb89c099d6db2Ruiyu Ni{
71569fc8f080e07ea026e8fbb8610cfb89c099d6db2Ruiyu Ni  EFI_STATUS                 Status;
71669fc8f080e07ea026e8fbb8610cfb89c099d6db2Ruiyu Ni  EDKII_SET_VARIABLE_STATUS  *SetVariableStatus;
71769fc8f080e07ea026e8fbb8610cfb89c099d6db2Ruiyu Ni  UINTN                      NameSize;
71869fc8f080e07ea026e8fbb8610cfb89c099d6db2Ruiyu Ni
71969fc8f080e07ea026e8fbb8610cfb89c099d6db2Ruiyu Ni  Status = gRT->SetVariable (
72069fc8f080e07ea026e8fbb8610cfb89c099d6db2Ruiyu Ni                  VariableName,
72169fc8f080e07ea026e8fbb8610cfb89c099d6db2Ruiyu Ni                  VendorGuid,
72269fc8f080e07ea026e8fbb8610cfb89c099d6db2Ruiyu Ni                  Attributes,
72369fc8f080e07ea026e8fbb8610cfb89c099d6db2Ruiyu Ni                  DataSize,
72469fc8f080e07ea026e8fbb8610cfb89c099d6db2Ruiyu Ni                  Data
72569fc8f080e07ea026e8fbb8610cfb89c099d6db2Ruiyu Ni                  );
72669fc8f080e07ea026e8fbb8610cfb89c099d6db2Ruiyu Ni  if (EFI_ERROR (Status)) {
72769fc8f080e07ea026e8fbb8610cfb89c099d6db2Ruiyu Ni    NameSize = StrSize (VariableName);
72869fc8f080e07ea026e8fbb8610cfb89c099d6db2Ruiyu Ni    SetVariableStatus = AllocatePool (sizeof (EDKII_SET_VARIABLE_STATUS) + NameSize + DataSize);
72969fc8f080e07ea026e8fbb8610cfb89c099d6db2Ruiyu Ni    if (SetVariableStatus != NULL) {
73069fc8f080e07ea026e8fbb8610cfb89c099d6db2Ruiyu Ni      CopyGuid (&SetVariableStatus->Guid, VendorGuid);
73169fc8f080e07ea026e8fbb8610cfb89c099d6db2Ruiyu Ni      SetVariableStatus->NameSize   = NameSize;
73269fc8f080e07ea026e8fbb8610cfb89c099d6db2Ruiyu Ni      SetVariableStatus->DataSize   = DataSize;
73369fc8f080e07ea026e8fbb8610cfb89c099d6db2Ruiyu Ni      SetVariableStatus->SetStatus  = Status;
73469fc8f080e07ea026e8fbb8610cfb89c099d6db2Ruiyu Ni      SetVariableStatus->Attributes = Attributes;
73569fc8f080e07ea026e8fbb8610cfb89c099d6db2Ruiyu Ni      CopyMem (SetVariableStatus + 1,                          VariableName, NameSize);
73669fc8f080e07ea026e8fbb8610cfb89c099d6db2Ruiyu Ni      CopyMem (((UINT8 *) (SetVariableStatus + 1)) + NameSize, Data,         DataSize);
73769fc8f080e07ea026e8fbb8610cfb89c099d6db2Ruiyu Ni
73869fc8f080e07ea026e8fbb8610cfb89c099d6db2Ruiyu Ni      REPORT_STATUS_CODE_EX (
73969fc8f080e07ea026e8fbb8610cfb89c099d6db2Ruiyu Ni        EFI_ERROR_CODE,
74069fc8f080e07ea026e8fbb8610cfb89c099d6db2Ruiyu Ni        PcdGet32 (PcdErrorCodeSetVariable),
74169fc8f080e07ea026e8fbb8610cfb89c099d6db2Ruiyu Ni        0,
74269fc8f080e07ea026e8fbb8610cfb89c099d6db2Ruiyu Ni        NULL,
74369fc8f080e07ea026e8fbb8610cfb89c099d6db2Ruiyu Ni        &gEdkiiStatusCodeDataTypeVariableGuid,
74469fc8f080e07ea026e8fbb8610cfb89c099d6db2Ruiyu Ni        SetVariableStatus,
74569fc8f080e07ea026e8fbb8610cfb89c099d6db2Ruiyu Ni        sizeof (EDKII_SET_VARIABLE_STATUS) + NameSize + DataSize
74669fc8f080e07ea026e8fbb8610cfb89c099d6db2Ruiyu Ni        );
74769fc8f080e07ea026e8fbb8610cfb89c099d6db2Ruiyu Ni
74869fc8f080e07ea026e8fbb8610cfb89c099d6db2Ruiyu Ni      FreePool (SetVariableStatus);
74969fc8f080e07ea026e8fbb8610cfb89c099d6db2Ruiyu Ni    }
75069fc8f080e07ea026e8fbb8610cfb89c099d6db2Ruiyu Ni  }
75169fc8f080e07ea026e8fbb8610cfb89c099d6db2Ruiyu Ni
75269fc8f080e07ea026e8fbb8610cfb89c099d6db2Ruiyu Ni  return Status;
75369fc8f080e07ea026e8fbb8610cfb89c099d6db2Ruiyu Ni}
75469fc8f080e07ea026e8fbb8610cfb89c099d6db2Ruiyu Ni
755