Home | History | Annotate | Download | only in BdsDxe
      1 /** @file
      2   This module produce main entry for BDS phase - BdsEntry.
      3   When this module was dispatched by DxeCore, gEfiBdsArchProtocolGuid will be installed
      4   which contains interface of BdsEntry.
      5   After DxeCore finish DXE phase, gEfiBdsArchProtocolGuid->BdsEntry will be invoked
      6   to enter BDS phase.
      7 
      8 Copyright (c) 2004 - 2016, Intel Corporation. All rights reserved.<BR>
      9 (C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>
     10 (C) Copyright 2015 Hewlett-Packard Development Company, L.P.<BR>
     11 This program and the accompanying materials
     12 are licensed and made available under the terms and conditions of the BSD License
     13 which accompanies this distribution.  The full text of the license may be found at
     14 http://opensource.org/licenses/bsd-license.php
     15 
     16 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     17 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     18 
     19 **/
     20 
     21 #include "Bds.h"
     22 #include "Language.h"
     23 #include "HwErrRecSupport.h"
     24 
     25 #define SET_BOOT_OPTION_SUPPORT_KEY_COUNT(a, c) {  \
     26       (a) = ((a) & ~EFI_BOOT_OPTION_SUPPORT_COUNT) | (((c) << LowBitSet32 (EFI_BOOT_OPTION_SUPPORT_COUNT)) & EFI_BOOT_OPTION_SUPPORT_COUNT); \
     27       }
     28 
     29 ///
     30 /// BDS arch protocol instance initial value.
     31 ///
     32 EFI_BDS_ARCH_PROTOCOL  gBds = {
     33   BdsEntry
     34 };
     35 
     36 //
     37 // gConnectConInEvent - Event which is signaled when ConIn connection is required
     38 //
     39 EFI_EVENT      gConnectConInEvent = NULL;
     40 
     41 ///
     42 /// The read-only variables defined in UEFI Spec.
     43 ///
     44 CHAR16  *mReadOnlyVariables[] = {
     45   EFI_PLATFORM_LANG_CODES_VARIABLE_NAME,
     46   EFI_LANG_CODES_VARIABLE_NAME,
     47   EFI_BOOT_OPTION_SUPPORT_VARIABLE_NAME,
     48   EFI_HW_ERR_REC_SUPPORT_VARIABLE_NAME,
     49   EFI_OS_INDICATIONS_SUPPORT_VARIABLE_NAME
     50   };
     51 
     52 CHAR16 *mBdsLoadOptionName[] = {
     53   L"Driver",
     54   L"SysPrep",
     55   L"Boot",
     56   L"PlatformRecovery"
     57 };
     58 
     59 /**
     60   Event to Connect ConIn.
     61 
     62   @param  Event                 Event whose notification function is being invoked.
     63   @param  Context               Pointer to the notification function's context,
     64                                 which is implementation-dependent.
     65 
     66 **/
     67 VOID
     68 EFIAPI
     69 BdsDxeOnConnectConInCallBack (
     70   IN EFI_EVENT                Event,
     71   IN VOID                     *Context
     72   )
     73 {
     74   EFI_STATUS Status;
     75 
     76   //
     77   // When Osloader call ReadKeyStroke to signal this event
     78   // no driver dependency is assumed existing. So use a non-dispatch version
     79   //
     80   Status = EfiBootManagerConnectConsoleVariable (ConIn);
     81   if (EFI_ERROR (Status)) {
     82     //
     83     // Should not enter this case, if enter, the keyboard will not work.
     84     // May need platfrom policy to connect keyboard.
     85     //
     86     DEBUG ((EFI_D_WARN, "[Bds] Connect ConIn failed - %r!!!\n", Status));
     87   }
     88 }
     89 /**
     90   Notify function for event group EFI_EVENT_GROUP_READY_TO_BOOT. This is used to
     91   check whether there is remaining deferred load images.
     92 
     93   @param[in]  Event   The Event that is being processed.
     94   @param[in]  Context The Event Context.
     95 
     96 **/
     97 VOID
     98 EFIAPI
     99 CheckDeferredLoadImageOnReadyToBoot (
    100   IN EFI_EVENT        Event,
    101   IN VOID             *Context
    102   )
    103 {
    104   EFI_STATUS                         Status;
    105   EFI_DEFERRED_IMAGE_LOAD_PROTOCOL   *DeferredImage;
    106   UINTN                              HandleCount;
    107   EFI_HANDLE                         *Handles;
    108   UINTN                              Index;
    109   UINTN                              ImageIndex;
    110   EFI_DEVICE_PATH_PROTOCOL           *ImageDevicePath;
    111   VOID                               *Image;
    112   UINTN                              ImageSize;
    113   BOOLEAN                            BootOption;
    114   CHAR16                             *DevicePathStr;
    115 
    116   //
    117   // Find all the deferred image load protocols.
    118   //
    119   HandleCount = 0;
    120   Handles = NULL;
    121   Status = gBS->LocateHandleBuffer (
    122     ByProtocol,
    123     &gEfiDeferredImageLoadProtocolGuid,
    124     NULL,
    125     &HandleCount,
    126     &Handles
    127   );
    128   if (EFI_ERROR (Status)) {
    129     return;
    130   }
    131 
    132   for (Index = 0; Index < HandleCount; Index++) {
    133     Status = gBS->HandleProtocol (Handles[Index], &gEfiDeferredImageLoadProtocolGuid, (VOID **) &DeferredImage);
    134     if (EFI_ERROR (Status)) {
    135       continue;
    136     }
    137 
    138     for (ImageIndex = 0; ; ImageIndex++) {
    139       //
    140       // Load all the deferred images in this protocol instance.
    141       //
    142       Status = DeferredImage->GetImageInfo (
    143         DeferredImage,
    144         ImageIndex,
    145         &ImageDevicePath,
    146         (VOID **) &Image,
    147         &ImageSize,
    148         &BootOption
    149       );
    150       if (EFI_ERROR (Status)) {
    151         break;
    152       }
    153       DevicePathStr = ConvertDevicePathToText (ImageDevicePath, FALSE, FALSE);
    154       DEBUG ((DEBUG_LOAD, "[Bds] Image was deferred but not loaded: %s.\n", DevicePathStr));
    155       if (DevicePathStr != NULL) {
    156         FreePool (DevicePathStr);
    157       }
    158     }
    159   }
    160   if (Handles != NULL) {
    161     FreePool (Handles);
    162   }
    163 }
    164 
    165 /**
    166 
    167   Install Boot Device Selection Protocol
    168 
    169   @param ImageHandle     The image handle.
    170   @param SystemTable     The system table.
    171 
    172   @retval  EFI_SUCEESS  BDS has finished initializing.
    173                         Return the dispatcher and recall BDS.Entry
    174   @retval  Other        Return status from AllocatePool() or gBS->InstallProtocolInterface
    175 
    176 **/
    177 EFI_STATUS
    178 EFIAPI
    179 BdsInitialize (
    180   IN EFI_HANDLE                            ImageHandle,
    181   IN EFI_SYSTEM_TABLE                      *SystemTable
    182   )
    183 {
    184   EFI_STATUS  Status;
    185   EFI_HANDLE  Handle;
    186   //
    187   // Install protocol interface
    188   //
    189   Handle = NULL;
    190   Status = gBS->InstallMultipleProtocolInterfaces (
    191                   &Handle,
    192                   &gEfiBdsArchProtocolGuid, &gBds,
    193                   NULL
    194                   );
    195   ASSERT_EFI_ERROR (Status);
    196 
    197   DEBUG_CODE (
    198     EFI_EVENT   Event;
    199     //
    200     // Register notify function to check deferred images on ReadyToBoot Event.
    201     //
    202     Status = gBS->CreateEventEx (
    203                     EVT_NOTIFY_SIGNAL,
    204                     TPL_CALLBACK,
    205                     CheckDeferredLoadImageOnReadyToBoot,
    206                     NULL,
    207                     &gEfiEventReadyToBootGuid,
    208                     &Event
    209                     );
    210     ASSERT_EFI_ERROR (Status);
    211   );
    212   return Status;
    213 }
    214 
    215 /**
    216   Function waits for a given event to fire, or for an optional timeout to expire.
    217 
    218   @param   Event              The event to wait for
    219   @param   Timeout            An optional timeout value in 100 ns units.
    220 
    221   @retval  EFI_SUCCESS      Event fired before Timeout expired.
    222   @retval  EFI_TIME_OUT     Timout expired before Event fired..
    223 
    224 **/
    225 EFI_STATUS
    226 BdsWaitForSingleEvent (
    227   IN  EFI_EVENT                  Event,
    228   IN  UINT64                     Timeout       OPTIONAL
    229   )
    230 {
    231   UINTN       Index;
    232   EFI_STATUS  Status;
    233   EFI_EVENT   TimerEvent;
    234   EFI_EVENT   WaitList[2];
    235 
    236   if (Timeout != 0) {
    237     //
    238     // Create a timer event
    239     //
    240     Status = gBS->CreateEvent (EVT_TIMER, 0, NULL, NULL, &TimerEvent);
    241     if (!EFI_ERROR (Status)) {
    242       //
    243       // Set the timer event
    244       //
    245       gBS->SetTimer (
    246              TimerEvent,
    247              TimerRelative,
    248              Timeout
    249              );
    250 
    251       //
    252       // Wait for the original event or the timer
    253       //
    254       WaitList[0] = Event;
    255       WaitList[1] = TimerEvent;
    256       Status      = gBS->WaitForEvent (2, WaitList, &Index);
    257       ASSERT_EFI_ERROR (Status);
    258       gBS->CloseEvent (TimerEvent);
    259 
    260       //
    261       // If the timer expired, change the return to timed out
    262       //
    263       if (Index == 1) {
    264         Status = EFI_TIMEOUT;
    265       }
    266     }
    267   } else {
    268     //
    269     // No timeout... just wait on the event
    270     //
    271     Status = gBS->WaitForEvent (1, &Event, &Index);
    272     ASSERT (!EFI_ERROR (Status));
    273     ASSERT (Index == 0);
    274   }
    275 
    276   return Status;
    277 }
    278 
    279 /**
    280   The function reads user inputs.
    281 
    282 **/
    283 VOID
    284 BdsReadKeys (
    285   VOID
    286   )
    287 {
    288   EFI_STATUS         Status;
    289   EFI_INPUT_KEY      Key;
    290 
    291   if (PcdGetBool (PcdConInConnectOnDemand)) {
    292     return;
    293   }
    294 
    295   while (gST->ConIn != NULL) {
    296 
    297     Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
    298 
    299     if (EFI_ERROR (Status)) {
    300       //
    301       // No more keys.
    302       //
    303       break;
    304     }
    305   }
    306 }
    307 
    308 /**
    309   The function waits for the boot manager timeout expires or hotkey is pressed.
    310 
    311   It calls PlatformBootManagerWaitCallback each second.
    312 
    313   @param     HotkeyTriggered   Input hotkey event.
    314 **/
    315 VOID
    316 BdsWait (
    317   IN EFI_EVENT      HotkeyTriggered
    318   )
    319 {
    320   EFI_STATUS            Status;
    321   UINT16                TimeoutRemain;
    322 
    323   DEBUG ((EFI_D_INFO, "[Bds]BdsWait ...Zzzzzzzzzzzz...\n"));
    324 
    325   TimeoutRemain = PcdGet16 (PcdPlatformBootTimeOut);
    326   while (TimeoutRemain != 0) {
    327     DEBUG ((EFI_D_INFO, "[Bds]BdsWait(%d)..Zzzz...\n", (UINTN) TimeoutRemain));
    328     PlatformBootManagerWaitCallback (TimeoutRemain);
    329 
    330     BdsReadKeys (); // BUGBUG: Only reading can signal HotkeyTriggered
    331                     //         Can be removed after all keyboard drivers invoke callback in timer callback.
    332 
    333     if (HotkeyTriggered != NULL) {
    334       Status = BdsWaitForSingleEvent (HotkeyTriggered, EFI_TIMER_PERIOD_SECONDS (1));
    335       if (!EFI_ERROR (Status)) {
    336         break;
    337       }
    338     } else {
    339       gBS->Stall (1000000);
    340     }
    341 
    342     //
    343     // 0xffff means waiting forever
    344     // BDS with no hotkey provided and 0xffff as timeout will "hang" in the loop
    345     //
    346     if (TimeoutRemain != 0xffff) {
    347       TimeoutRemain--;
    348     }
    349   }
    350   DEBUG ((EFI_D_INFO, "[Bds]Exit the waiting!\n"));
    351 }
    352 
    353 /**
    354   Attempt to boot each boot option in the BootOptions array.
    355 
    356   @param BootOptions       Input boot option array.
    357   @param BootOptionCount   Input boot option count.
    358   @param BootManagerMenu   Input boot manager menu.
    359 
    360   @retval TRUE  Successfully boot one of the boot options.
    361   @retval FALSE Failed boot any of the boot options.
    362 **/
    363 BOOLEAN
    364 BootBootOptions (
    365   IN EFI_BOOT_MANAGER_LOAD_OPTION    *BootOptions,
    366   IN UINTN                           BootOptionCount,
    367   IN EFI_BOOT_MANAGER_LOAD_OPTION    *BootManagerMenu OPTIONAL
    368   )
    369 {
    370   UINTN                              Index;
    371 
    372   //
    373   // Attempt boot each boot option
    374   //
    375   for (Index = 0; Index < BootOptionCount; Index++) {
    376     //
    377     // According to EFI Specification, if a load option is not marked
    378     // as LOAD_OPTION_ACTIVE, the boot manager will not automatically
    379     // load the option.
    380     //
    381     if ((BootOptions[Index].Attributes & LOAD_OPTION_ACTIVE) == 0) {
    382       continue;
    383     }
    384 
    385     //
    386     // Boot#### load options with LOAD_OPTION_CATEGORY_APP are executables which are not
    387     // part of the normal boot processing. Boot options with reserved category values will be
    388     // ignored by the boot manager.
    389     //
    390     if ((BootOptions[Index].Attributes & LOAD_OPTION_CATEGORY) != LOAD_OPTION_CATEGORY_BOOT) {
    391       continue;
    392     }
    393 
    394     //
    395     // All the driver options should have been processed since
    396     // now boot will be performed.
    397     //
    398     EfiBootManagerBoot (&BootOptions[Index]);
    399 
    400     //
    401     // If the boot via Boot#### returns with a status of EFI_SUCCESS, platform firmware
    402     // supports boot manager menu, and if firmware is configured to boot in an
    403     // interactive mode, the boot manager will stop processing the BootOrder variable and
    404     // present a boot manager menu to the user.
    405     //
    406     if ((BootManagerMenu != NULL) && (BootOptions[Index].Status == EFI_SUCCESS)) {
    407       EfiBootManagerBoot (BootManagerMenu);
    408       break;
    409     }
    410   }
    411 
    412   return (BOOLEAN) (Index < BootOptionCount);
    413 }
    414 
    415 /**
    416   The function will load and start every Driver####, SysPrep#### or PlatformRecovery####.
    417 
    418   @param  LoadOptions        Load option array.
    419   @param  LoadOptionCount    Load option count.
    420 **/
    421 VOID
    422 ProcessLoadOptions (
    423   IN EFI_BOOT_MANAGER_LOAD_OPTION       *LoadOptions,
    424   IN UINTN                              LoadOptionCount
    425   )
    426 {
    427   EFI_STATUS                        Status;
    428   UINTN                             Index;
    429   BOOLEAN                           ReconnectAll;
    430   EFI_BOOT_MANAGER_LOAD_OPTION_TYPE LoadOptionType;
    431 
    432   ReconnectAll   = FALSE;
    433   LoadOptionType = LoadOptionTypeMax;
    434 
    435   //
    436   // Process the driver option
    437   //
    438   for (Index = 0; Index < LoadOptionCount; Index++) {
    439     //
    440     // All the load options in the array should be of the same type.
    441     //
    442     if (Index == 0) {
    443       LoadOptionType = LoadOptions[Index].OptionType;
    444     }
    445     ASSERT (LoadOptionType == LoadOptions[Index].OptionType);
    446     ASSERT (LoadOptionType != LoadOptionTypeBoot);
    447 
    448     Status = EfiBootManagerProcessLoadOption (&LoadOptions[Index]);
    449 
    450     //
    451     // Status indicates whether the load option is loaded and executed
    452     // LoadOptions[Index].Status is what the load option returns
    453     //
    454     if (!EFI_ERROR (Status)) {
    455       //
    456       // Stop processing if any PlatformRecovery#### returns success.
    457       //
    458       if ((LoadOptions[Index].Status == EFI_SUCCESS) &&
    459           (LoadOptionType == LoadOptionTypePlatformRecovery)) {
    460         break;
    461       }
    462 
    463       //
    464       // Only set ReconnectAll flag when the load option executes successfully.
    465       //
    466       if (!EFI_ERROR (LoadOptions[Index].Status) &&
    467           (LoadOptions[Index].Attributes & LOAD_OPTION_FORCE_RECONNECT) != 0) {
    468         ReconnectAll = TRUE;
    469       }
    470     }
    471   }
    472 
    473   //
    474   // If a driver load option is marked as LOAD_OPTION_FORCE_RECONNECT,
    475   // then all of the EFI drivers in the system will be disconnected and
    476   // reconnected after the last driver load option is processed.
    477   //
    478   if (ReconnectAll && LoadOptionType == LoadOptionTypeDriver) {
    479     EfiBootManagerDisconnectAll ();
    480     EfiBootManagerConnectAll ();
    481   }
    482 }
    483 
    484 /**
    485 
    486   Validate input console variable data.
    487 
    488   If found the device path is not a valid device path, remove the variable.
    489 
    490   @param VariableName             Input console variable name.
    491 
    492 **/
    493 VOID
    494 BdsFormalizeConsoleVariable (
    495   IN  CHAR16          *VariableName
    496   )
    497 {
    498   EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
    499   UINTN                     VariableSize;
    500   EFI_STATUS                Status;
    501 
    502   GetEfiGlobalVariable2 (VariableName, (VOID **) &DevicePath, &VariableSize);
    503   if ((DevicePath != NULL) && !IsDevicePathValid (DevicePath, VariableSize)) {
    504     Status = gRT->SetVariable (
    505                     VariableName,
    506                     &gEfiGlobalVariableGuid,
    507                     EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
    508                     0,
    509                     NULL
    510                     );
    511     //
    512     // Deleting variable with current variable implementation shouldn't fail.
    513     //
    514     ASSERT_EFI_ERROR (Status);
    515   }
    516 
    517   if (DevicePath != NULL) {
    518     FreePool (DevicePath);
    519   }
    520 }
    521 
    522 /**
    523   Formalize OsIndication related variables.
    524 
    525   For OsIndicationsSupported, Create a BS/RT/UINT64 variable to report caps
    526   Delete OsIndications variable if it is not NV/BS/RT UINT64.
    527 
    528   Item 3 is used to solve case when OS corrupts OsIndications. Here simply delete this NV variable.
    529 
    530   Create a boot option for BootManagerMenu if it hasn't been created yet
    531 
    532 **/
    533 VOID
    534 BdsFormalizeOSIndicationVariable (
    535   VOID
    536   )
    537 {
    538   EFI_STATUS                      Status;
    539   UINT64                          OsIndicationSupport;
    540   UINT64                          OsIndication;
    541   UINTN                           DataSize;
    542   UINT32                          Attributes;
    543   EFI_BOOT_MANAGER_LOAD_OPTION    BootManagerMenu;
    544 
    545   //
    546   // OS indicater support variable
    547   //
    548   Status = EfiBootManagerGetBootManagerMenu (&BootManagerMenu);
    549   if (Status != EFI_NOT_FOUND) {
    550     OsIndicationSupport = EFI_OS_INDICATIONS_BOOT_TO_FW_UI | EFI_OS_INDICATIONS_START_PLATFORM_RECOVERY;
    551     EfiBootManagerFreeLoadOption (&BootManagerMenu);
    552   } else {
    553     OsIndicationSupport = EFI_OS_INDICATIONS_START_PLATFORM_RECOVERY;
    554   }
    555 
    556   Status = gRT->SetVariable (
    557                   EFI_OS_INDICATIONS_SUPPORT_VARIABLE_NAME,
    558                   &gEfiGlobalVariableGuid,
    559                   EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
    560                   sizeof(UINT64),
    561                   &OsIndicationSupport
    562                   );
    563   //
    564   // Platform needs to make sure setting volatile variable before calling 3rd party code shouldn't fail.
    565   //
    566   ASSERT_EFI_ERROR (Status);
    567 
    568   //
    569   // If OsIndications is invalid, remove it.
    570   // Invalid case
    571   //   1. Data size != UINT64
    572   //   2. OsIndication value inconsistence
    573   //   3. OsIndication attribute inconsistence
    574   //
    575   OsIndication = 0;
    576   Attributes = 0;
    577   DataSize = sizeof(UINT64);
    578   Status = gRT->GetVariable (
    579                   EFI_OS_INDICATIONS_VARIABLE_NAME,
    580                   &gEfiGlobalVariableGuid,
    581                   &Attributes,
    582                   &DataSize,
    583                   &OsIndication
    584                   );
    585   if (Status == EFI_NOT_FOUND) {
    586     return;
    587   }
    588 
    589   if ((DataSize != sizeof (OsIndication)) ||
    590       ((OsIndication & ~OsIndicationSupport) != 0) ||
    591       (Attributes != (EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE))
    592      ){
    593 
    594     DEBUG ((EFI_D_ERROR, "[Bds] Unformalized OsIndications variable exists. Delete it\n"));
    595     Status = gRT->SetVariable (
    596                     EFI_OS_INDICATIONS_VARIABLE_NAME,
    597                     &gEfiGlobalVariableGuid,
    598                     0,
    599                     0,
    600                     NULL
    601                     );
    602     //
    603     // Deleting variable with current variable implementation shouldn't fail.
    604     //
    605     ASSERT_EFI_ERROR(Status);
    606   }
    607 }
    608 
    609 /**
    610 
    611   Validate variables.
    612 
    613 **/
    614 VOID
    615 BdsFormalizeEfiGlobalVariable (
    616   VOID
    617   )
    618 {
    619   //
    620   // Validate Console variable.
    621   //
    622   BdsFormalizeConsoleVariable (EFI_CON_IN_VARIABLE_NAME);
    623   BdsFormalizeConsoleVariable (EFI_CON_OUT_VARIABLE_NAME);
    624   BdsFormalizeConsoleVariable (EFI_ERR_OUT_VARIABLE_NAME);
    625 
    626   //
    627   // Validate OSIndication related variable.
    628   //
    629   BdsFormalizeOSIndicationVariable ();
    630 }
    631 
    632 /**
    633 
    634   Allocate a block of memory that will contain performance data to OS.
    635 
    636 **/
    637 VOID
    638 BdsAllocateMemoryForPerformanceData (
    639   VOID
    640   )
    641 {
    642   EFI_STATUS                    Status;
    643   EFI_PHYSICAL_ADDRESS          AcpiLowMemoryBase;
    644   EDKII_VARIABLE_LOCK_PROTOCOL  *VariableLock;
    645 
    646   AcpiLowMemoryBase = 0x0FFFFFFFFULL;
    647 
    648   //
    649   // Allocate a block of memory that will contain performance data to OS.
    650   //
    651   Status = gBS->AllocatePages (
    652                   AllocateMaxAddress,
    653                   EfiReservedMemoryType,
    654                   EFI_SIZE_TO_PAGES (PERF_DATA_MAX_LENGTH),
    655                   &AcpiLowMemoryBase
    656                   );
    657   if (!EFI_ERROR (Status)) {
    658     //
    659     // Save the pointer to variable for use in S3 resume.
    660     //
    661     Status = BdsDxeSetVariableAndReportStatusCodeOnError (
    662                L"PerfDataMemAddr",
    663                &gPerformanceProtocolGuid,
    664                EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
    665                sizeof (EFI_PHYSICAL_ADDRESS),
    666                &AcpiLowMemoryBase
    667                );
    668     if (EFI_ERROR (Status)) {
    669       DEBUG ((EFI_D_ERROR, "[Bds] PerfDataMemAddr (%08x) cannot be saved to NV storage.\n", AcpiLowMemoryBase));
    670     }
    671     //
    672     // Mark L"PerfDataMemAddr" variable to read-only if the Variable Lock protocol exists
    673     // Still lock it even the variable cannot be saved to prevent it's set by 3rd party code.
    674     //
    675     Status = gBS->LocateProtocol (&gEdkiiVariableLockProtocolGuid, NULL, (VOID **) &VariableLock);
    676     if (!EFI_ERROR (Status)) {
    677       Status = VariableLock->RequestToLock (VariableLock, L"PerfDataMemAddr", &gPerformanceProtocolGuid);
    678       ASSERT_EFI_ERROR (Status);
    679     }
    680   }
    681 }
    682 
    683 /**
    684 
    685   Service routine for BdsInstance->Entry(). Devices are connected, the
    686   consoles are initialized, and the boot options are tried.
    687 
    688   @param This             Protocol Instance structure.
    689 
    690 **/
    691 VOID
    692 EFIAPI
    693 BdsEntry (
    694   IN EFI_BDS_ARCH_PROTOCOL  *This
    695   )
    696 {
    697   EFI_BOOT_MANAGER_LOAD_OPTION    *LoadOptions;
    698   UINTN                           LoadOptionCount;
    699   CHAR16                          *FirmwareVendor;
    700   EFI_EVENT                       HotkeyTriggered;
    701   UINT64                          OsIndication;
    702   UINTN                           DataSize;
    703   EFI_STATUS                      Status;
    704   UINT32                          BootOptionSupport;
    705   UINT16                          BootTimeOut;
    706   EDKII_VARIABLE_LOCK_PROTOCOL    *VariableLock;
    707   UINTN                           Index;
    708   EFI_BOOT_MANAGER_LOAD_OPTION    LoadOption;
    709   UINT16                          *BootNext;
    710   CHAR16                          BootNextVariableName[sizeof ("Boot####")];
    711   EFI_BOOT_MANAGER_LOAD_OPTION    BootManagerMenu;
    712   BOOLEAN                         BootFwUi;
    713   BOOLEAN                         PlatformRecovery;
    714   BOOLEAN                         BootSuccess;
    715   EFI_DEVICE_PATH_PROTOCOL        *FilePath;
    716   EFI_STATUS                      BootManagerMenuStatus;
    717 
    718   HotkeyTriggered = NULL;
    719   Status          = EFI_SUCCESS;
    720   BootSuccess     = FALSE;
    721 
    722   //
    723   // Insert the performance probe
    724   //
    725   PERF_END (NULL, "DXE", NULL, 0);
    726   PERF_START (NULL, "BDS", NULL, 0);
    727   DEBUG ((EFI_D_INFO, "[Bds] Entry...\n"));
    728 
    729   PERF_CODE (
    730     BdsAllocateMemoryForPerformanceData ();
    731   );
    732 
    733   //
    734   // Fill in FirmwareVendor and FirmwareRevision from PCDs
    735   //
    736   FirmwareVendor = (CHAR16 *) PcdGetPtr (PcdFirmwareVendor);
    737   gST->FirmwareVendor = AllocateRuntimeCopyPool (StrSize (FirmwareVendor), FirmwareVendor);
    738   ASSERT (gST->FirmwareVendor != NULL);
    739   gST->FirmwareRevision = PcdGet32 (PcdFirmwareRevision);
    740 
    741   //
    742   // Fixup Tasble CRC after we updated Firmware Vendor and Revision
    743   //
    744   gST->Hdr.CRC32 = 0;
    745   gBS->CalculateCrc32 ((VOID *) gST, sizeof (EFI_SYSTEM_TABLE), &gST->Hdr.CRC32);
    746 
    747   //
    748   // Validate Variable.
    749   //
    750   BdsFormalizeEfiGlobalVariable ();
    751 
    752   //
    753   // Mark the read-only variables if the Variable Lock protocol exists
    754   //
    755   Status = gBS->LocateProtocol (&gEdkiiVariableLockProtocolGuid, NULL, (VOID **) &VariableLock);
    756   DEBUG ((EFI_D_INFO, "[BdsDxe] Locate Variable Lock protocol - %r\n", Status));
    757   if (!EFI_ERROR (Status)) {
    758     for (Index = 0; Index < ARRAY_SIZE (mReadOnlyVariables); Index++) {
    759       Status = VariableLock->RequestToLock (VariableLock, mReadOnlyVariables[Index], &gEfiGlobalVariableGuid);
    760       ASSERT_EFI_ERROR (Status);
    761     }
    762   }
    763 
    764   InitializeHwErrRecSupport ();
    765 
    766   //
    767   // Initialize L"Timeout" EFI global variable.
    768   //
    769   BootTimeOut = PcdGet16 (PcdPlatformBootTimeOut);
    770   if (BootTimeOut != 0xFFFF) {
    771     //
    772     // If time out value equal 0xFFFF, no need set to 0xFFFF to variable area because UEFI specification
    773     // define same behavior between no value or 0xFFFF value for L"Timeout".
    774     //
    775     BdsDxeSetVariableAndReportStatusCodeOnError (
    776       EFI_TIME_OUT_VARIABLE_NAME,
    777       &gEfiGlobalVariableGuid,
    778       EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
    779       sizeof (UINT16),
    780       &BootTimeOut
    781       );
    782   }
    783 
    784   //
    785   // Initialize L"BootOptionSupport" EFI global variable.
    786   // Lazy-ConIn implictly disables BDS hotkey.
    787   //
    788   BootOptionSupport = EFI_BOOT_OPTION_SUPPORT_APP | EFI_BOOT_OPTION_SUPPORT_SYSPREP;
    789   if (!PcdGetBool (PcdConInConnectOnDemand)) {
    790     BootOptionSupport |= EFI_BOOT_OPTION_SUPPORT_KEY;
    791     SET_BOOT_OPTION_SUPPORT_KEY_COUNT (BootOptionSupport, 3);
    792   }
    793   Status = gRT->SetVariable (
    794                   EFI_BOOT_OPTION_SUPPORT_VARIABLE_NAME,
    795                   &gEfiGlobalVariableGuid,
    796                   EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
    797                   sizeof (BootOptionSupport),
    798                   &BootOptionSupport
    799                   );
    800   //
    801   // Platform needs to make sure setting volatile variable before calling 3rd party code shouldn't fail.
    802   //
    803   ASSERT_EFI_ERROR (Status);
    804 
    805   //
    806   // Cache and remove the "BootNext" NV variable.
    807   //
    808   GetEfiGlobalVariable2 (EFI_BOOT_NEXT_VARIABLE_NAME, (VOID **) &BootNext, &DataSize);
    809   if (DataSize != sizeof (UINT16)) {
    810     if (BootNext != NULL) {
    811       FreePool (BootNext);
    812     }
    813     BootNext = NULL;
    814   }
    815   Status = gRT->SetVariable (
    816                   EFI_BOOT_NEXT_VARIABLE_NAME,
    817                   &gEfiGlobalVariableGuid,
    818                   0,
    819                   0,
    820                   NULL
    821                   );
    822   //
    823   // Deleting NV variable shouldn't fail unless it doesn't exist.
    824   //
    825   ASSERT (Status == EFI_SUCCESS || Status == EFI_NOT_FOUND);
    826 
    827   //
    828   // Initialize the platform language variables
    829   //
    830   InitializeLanguage (TRUE);
    831 
    832   //
    833   // System firmware must include a PlatformRecovery#### variable specifying
    834   // a short-form File Path Media Device Path containing the platform default
    835   // file path for removable media
    836   //
    837   FilePath = FileDevicePath (NULL, EFI_REMOVABLE_MEDIA_FILE_NAME);
    838   Status = EfiBootManagerInitializeLoadOption (
    839              &LoadOption,
    840              LoadOptionNumberUnassigned,
    841              LoadOptionTypePlatformRecovery,
    842              LOAD_OPTION_ACTIVE,
    843              L"Default PlatformRecovery",
    844              FilePath,
    845              NULL,
    846              0
    847              );
    848   ASSERT_EFI_ERROR (Status);
    849   LoadOptions = EfiBootManagerGetLoadOptions (&LoadOptionCount, LoadOptionTypePlatformRecovery);
    850   if (EfiBootManagerFindLoadOption (&LoadOption, LoadOptions, LoadOptionCount) == -1) {
    851     for (Index = 0; Index < LoadOptionCount; Index++) {
    852       //
    853       // The PlatformRecovery#### options are sorted by OptionNumber.
    854       // Find the the smallest unused number as the new OptionNumber.
    855       //
    856       if (LoadOptions[Index].OptionNumber != Index) {
    857         break;
    858       }
    859     }
    860     LoadOption.OptionNumber = Index;
    861     Status = EfiBootManagerLoadOptionToVariable (&LoadOption);
    862     ASSERT_EFI_ERROR (Status);
    863   }
    864   EfiBootManagerFreeLoadOption (&LoadOption);
    865   FreePool (FilePath);
    866   EfiBootManagerFreeLoadOptions (LoadOptions, LoadOptionCount);
    867 
    868   //
    869   // Report Status Code to indicate connecting drivers will happen
    870   //
    871   REPORT_STATUS_CODE (
    872     EFI_PROGRESS_CODE,
    873     (EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_DXE_BS_PC_BEGIN_CONNECTING_DRIVERS)
    874     );
    875 
    876   //
    877   // Initialize ConnectConIn event before calling platform code.
    878   //
    879   if (PcdGetBool (PcdConInConnectOnDemand)) {
    880     Status = gBS->CreateEventEx (
    881                     EVT_NOTIFY_SIGNAL,
    882                     TPL_CALLBACK,
    883                     BdsDxeOnConnectConInCallBack,
    884                     NULL,
    885                     &gConnectConInEventGuid,
    886                     &gConnectConInEvent
    887                     );
    888     if (EFI_ERROR (Status)) {
    889       gConnectConInEvent = NULL;
    890     }
    891   }
    892 
    893   //
    894   // Do the platform init, can be customized by OEM/IBV
    895   // Possible things that can be done in PlatformBootManagerBeforeConsole:
    896   // > Update console variable: 1. include hot-plug devices; 2. Clear ConIn and add SOL for AMT
    897   // > Register new Driver#### or Boot####
    898   // > Register new Key####: e.g.: F12
    899   // > Signal ReadyToLock event
    900   // > Authentication action: 1. connect Auth devices; 2. Identify auto logon user.
    901   //
    902   PERF_START (NULL, "PlatformBootManagerBeforeConsole", "BDS", 0);
    903   PlatformBootManagerBeforeConsole ();
    904   PERF_END   (NULL, "PlatformBootManagerBeforeConsole", "BDS", 0);
    905 
    906   //
    907   // Initialize hotkey service
    908   //
    909   EfiBootManagerStartHotkeyService (&HotkeyTriggered);
    910 
    911   //
    912   // Execute Driver Options
    913   //
    914   LoadOptions = EfiBootManagerGetLoadOptions (&LoadOptionCount, LoadOptionTypeDriver);
    915   ProcessLoadOptions (LoadOptions, LoadOptionCount);
    916   EfiBootManagerFreeLoadOptions (LoadOptions, LoadOptionCount);
    917 
    918   //
    919   // Connect consoles
    920   //
    921   PERF_START (NULL, "EfiBootManagerConnectAllDefaultConsoles", "BDS", 0);
    922   if (PcdGetBool (PcdConInConnectOnDemand)) {
    923     EfiBootManagerConnectConsoleVariable (ConOut);
    924     EfiBootManagerConnectConsoleVariable (ErrOut);
    925     //
    926     // Do not connect ConIn devices when lazy ConIn feature is ON.
    927     //
    928   } else {
    929     EfiBootManagerConnectAllDefaultConsoles ();
    930   }
    931   PERF_END   (NULL, "EfiBootManagerConnectAllDefaultConsoles", "BDS", 0);
    932 
    933   //
    934   // Do the platform specific action after the console is ready
    935   // Possible things that can be done in PlatformBootManagerAfterConsole:
    936   // > Console post action:
    937   //   > Dynamically switch output mode from 100x31 to 80x25 for certain senarino
    938   //   > Signal console ready platform customized event
    939   // > Run diagnostics like memory testing
    940   // > Connect certain devices
    941   // > Dispatch aditional option roms
    942   // > Special boot: e.g.: USB boot, enter UI
    943   //
    944   PERF_START (NULL, "PlatformBootManagerAfterConsole", "BDS", 0);
    945   PlatformBootManagerAfterConsole ();
    946   PERF_END   (NULL, "PlatformBootManagerAfterConsole", "BDS", 0);
    947   //
    948   // Boot to Boot Manager Menu when EFI_OS_INDICATIONS_BOOT_TO_FW_UI is set. Skip HotkeyBoot
    949   //
    950   DataSize = sizeof (UINT64);
    951   Status = gRT->GetVariable (
    952                   EFI_OS_INDICATIONS_VARIABLE_NAME,
    953                   &gEfiGlobalVariableGuid,
    954                   NULL,
    955                   &DataSize,
    956                   &OsIndication
    957                   );
    958   if (EFI_ERROR (Status)) {
    959     OsIndication = 0;
    960   }
    961 
    962   DEBUG_CODE (
    963     EFI_BOOT_MANAGER_LOAD_OPTION_TYPE LoadOptionType;
    964     DEBUG ((EFI_D_INFO, "[Bds]OsIndication: %016x\n", OsIndication));
    965     DEBUG ((EFI_D_INFO, "[Bds]=============Begin Load Options Dumping ...=============\n"));
    966     for (LoadOptionType = 0; LoadOptionType < LoadOptionTypeMax; LoadOptionType++) {
    967       DEBUG ((
    968         EFI_D_INFO, "  %s Options:\n",
    969         mBdsLoadOptionName[LoadOptionType]
    970         ));
    971       LoadOptions = EfiBootManagerGetLoadOptions (&LoadOptionCount, LoadOptionType);
    972       for (Index = 0; Index < LoadOptionCount; Index++) {
    973         DEBUG ((
    974           EFI_D_INFO, "    %s%04x: %s \t\t 0x%04x\n",
    975           mBdsLoadOptionName[LoadOptionType],
    976           LoadOptions[Index].OptionNumber,
    977           LoadOptions[Index].Description,
    978           LoadOptions[Index].Attributes
    979           ));
    980       }
    981       EfiBootManagerFreeLoadOptions (LoadOptions, LoadOptionCount);
    982     }
    983     DEBUG ((EFI_D_INFO, "[Bds]=============End Load Options Dumping=============\n"));
    984   );
    985 
    986   //
    987   // BootManagerMenu doesn't contain the correct information when return status is EFI_NOT_FOUND.
    988   //
    989   BootManagerMenuStatus = EfiBootManagerGetBootManagerMenu (&BootManagerMenu);
    990 
    991   BootFwUi         = (BOOLEAN) ((OsIndication & EFI_OS_INDICATIONS_BOOT_TO_FW_UI) != 0);
    992   PlatformRecovery = (BOOLEAN) ((OsIndication & EFI_OS_INDICATIONS_START_PLATFORM_RECOVERY) != 0);
    993   //
    994   // Clear EFI_OS_INDICATIONS_BOOT_TO_FW_UI to acknowledge OS
    995   //
    996   if (BootFwUi || PlatformRecovery) {
    997     OsIndication &= ~((UINT64) (EFI_OS_INDICATIONS_BOOT_TO_FW_UI | EFI_OS_INDICATIONS_START_PLATFORM_RECOVERY));
    998     Status = gRT->SetVariable (
    999                EFI_OS_INDICATIONS_VARIABLE_NAME,
   1000                &gEfiGlobalVariableGuid,
   1001                EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
   1002                sizeof(UINT64),
   1003                &OsIndication
   1004                );
   1005     //
   1006     // Changing the content without increasing its size with current variable implementation shouldn't fail.
   1007     //
   1008     ASSERT_EFI_ERROR (Status);
   1009   }
   1010 
   1011   //
   1012   // Launch Boot Manager Menu directly when EFI_OS_INDICATIONS_BOOT_TO_FW_UI is set. Skip HotkeyBoot
   1013   //
   1014   if (BootFwUi && (BootManagerMenuStatus != EFI_NOT_FOUND)) {
   1015     //
   1016     // Follow generic rule, Call BdsDxeOnConnectConInCallBack to connect ConIn before enter UI
   1017     //
   1018     if (PcdGetBool (PcdConInConnectOnDemand)) {
   1019       BdsDxeOnConnectConInCallBack (NULL, NULL);
   1020     }
   1021 
   1022     //
   1023     // Directly enter the setup page.
   1024     //
   1025     EfiBootManagerBoot (&BootManagerMenu);
   1026   }
   1027 
   1028   if (!PlatformRecovery) {
   1029     //
   1030     // Execute SysPrep####
   1031     //
   1032     LoadOptions = EfiBootManagerGetLoadOptions (&LoadOptionCount, LoadOptionTypeSysPrep);
   1033     ProcessLoadOptions (LoadOptions, LoadOptionCount);
   1034     EfiBootManagerFreeLoadOptions (LoadOptions, LoadOptionCount);
   1035 
   1036     //
   1037     // Execute Key####
   1038     //
   1039     PERF_START (NULL, "BdsWait", "BDS", 0);
   1040     BdsWait (HotkeyTriggered);
   1041     PERF_END   (NULL, "BdsWait", "BDS", 0);
   1042 
   1043     //
   1044     // BdsReadKeys() can be removed after all keyboard drivers invoke callback in timer callback.
   1045     //
   1046     BdsReadKeys ();
   1047 
   1048     EfiBootManagerHotkeyBoot ();
   1049 
   1050     //
   1051     // Boot to "BootNext"
   1052     //
   1053     if (BootNext != NULL) {
   1054       UnicodeSPrint (BootNextVariableName, sizeof (BootNextVariableName), L"Boot%04x", *BootNext);
   1055       Status = EfiBootManagerVariableToLoadOption (BootNextVariableName, &LoadOption);
   1056       if (!EFI_ERROR (Status)) {
   1057         EfiBootManagerBoot (&LoadOption);
   1058         EfiBootManagerFreeLoadOption (&LoadOption);
   1059         if ((LoadOption.Status == EFI_SUCCESS) &&
   1060             (BootManagerMenuStatus != EFI_NOT_FOUND) &&
   1061             (LoadOption.OptionNumber != BootManagerMenu.OptionNumber)) {
   1062           //
   1063           // Boot to Boot Manager Menu upon EFI_SUCCESS
   1064           // Exception: Do not boot again when the BootNext points to Boot Manager Menu.
   1065           //
   1066           EfiBootManagerBoot (&BootManagerMenu);
   1067         }
   1068       }
   1069     }
   1070 
   1071     do {
   1072       //
   1073       // Retry to boot if any of the boot succeeds
   1074       //
   1075       LoadOptions = EfiBootManagerGetLoadOptions (&LoadOptionCount, LoadOptionTypeBoot);
   1076       BootSuccess = BootBootOptions (LoadOptions, LoadOptionCount, (BootManagerMenuStatus != EFI_NOT_FOUND) ? &BootManagerMenu : NULL);
   1077       EfiBootManagerFreeLoadOptions (LoadOptions, LoadOptionCount);
   1078     } while (BootSuccess);
   1079   }
   1080 
   1081   if (BootManagerMenuStatus != EFI_NOT_FOUND) {
   1082     EfiBootManagerFreeLoadOption (&BootManagerMenu);
   1083   }
   1084 
   1085   if (!BootSuccess) {
   1086     LoadOptions = EfiBootManagerGetLoadOptions (&LoadOptionCount, LoadOptionTypePlatformRecovery);
   1087     ProcessLoadOptions (LoadOptions, LoadOptionCount);
   1088     EfiBootManagerFreeLoadOptions (LoadOptions, LoadOptionCount);
   1089   }
   1090 
   1091   DEBUG ((EFI_D_ERROR, "[Bds] Unable to boot!\n"));
   1092   CpuDeadLoop ();
   1093 }
   1094 
   1095 /**
   1096   Set the variable and report the error through status code upon failure.
   1097 
   1098   @param  VariableName           A Null-terminated string that is the name of the vendor's variable.
   1099                                  Each VariableName is unique for each VendorGuid. VariableName must
   1100                                  contain 1 or more characters. If VariableName is an empty string,
   1101                                  then EFI_INVALID_PARAMETER is returned.
   1102   @param  VendorGuid             A unique identifier for the vendor.
   1103   @param  Attributes             Attributes bitmask to set for the variable.
   1104   @param  DataSize               The size in bytes of the Data buffer. Unless the EFI_VARIABLE_APPEND_WRITE,
   1105                                  EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS, or
   1106                                  EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS attribute is set, a size of zero
   1107                                  causes the variable to be deleted. When the EFI_VARIABLE_APPEND_WRITE attribute is
   1108                                  set, then a SetVariable() call with a DataSize of zero will not cause any change to
   1109                                  the variable value (the timestamp associated with the variable may be updated however
   1110                                  even if no new data value is provided,see the description of the
   1111                                  EFI_VARIABLE_AUTHENTICATION_2 descriptor below. In this case the DataSize will not
   1112                                  be zero since the EFI_VARIABLE_AUTHENTICATION_2 descriptor will be populated).
   1113   @param  Data                   The contents for the variable.
   1114 
   1115   @retval EFI_SUCCESS            The firmware has successfully stored the variable and its data as
   1116                                  defined by the Attributes.
   1117   @retval EFI_INVALID_PARAMETER  An invalid combination of attribute bits, name, and GUID was supplied, or the
   1118                                  DataSize exceeds the maximum allowed.
   1119   @retval EFI_INVALID_PARAMETER  VariableName is an empty string.
   1120   @retval EFI_OUT_OF_RESOURCES   Not enough storage is available to hold the variable and its data.
   1121   @retval EFI_DEVICE_ERROR       The variable could not be retrieved due to a hardware error.
   1122   @retval EFI_WRITE_PROTECTED    The variable in question is read-only.
   1123   @retval EFI_WRITE_PROTECTED    The variable in question cannot be deleted.
   1124   @retval EFI_SECURITY_VIOLATION The variable could not be written due to EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS
   1125                                  or EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACESS being set, but the AuthInfo
   1126                                  does NOT pass the validation check carried out by the firmware.
   1127 
   1128   @retval EFI_NOT_FOUND          The variable trying to be updated or deleted was not found.
   1129 **/
   1130 EFI_STATUS
   1131 BdsDxeSetVariableAndReportStatusCodeOnError (
   1132   IN CHAR16     *VariableName,
   1133   IN EFI_GUID   *VendorGuid,
   1134   IN UINT32     Attributes,
   1135   IN UINTN      DataSize,
   1136   IN VOID       *Data
   1137   )
   1138 {
   1139   EFI_STATUS                 Status;
   1140   EDKII_SET_VARIABLE_STATUS  *SetVariableStatus;
   1141   UINTN                      NameSize;
   1142 
   1143   Status = gRT->SetVariable (
   1144                   VariableName,
   1145                   VendorGuid,
   1146                   Attributes,
   1147                   DataSize,
   1148                   Data
   1149                   );
   1150   if (EFI_ERROR (Status)) {
   1151     NameSize = StrSize (VariableName);
   1152     SetVariableStatus = AllocatePool (sizeof (EDKII_SET_VARIABLE_STATUS) + NameSize + DataSize);
   1153     if (SetVariableStatus != NULL) {
   1154       CopyGuid (&SetVariableStatus->Guid, VendorGuid);
   1155       SetVariableStatus->NameSize   = NameSize;
   1156       SetVariableStatus->DataSize   = DataSize;
   1157       SetVariableStatus->SetStatus  = Status;
   1158       SetVariableStatus->Attributes = Attributes;
   1159       CopyMem (SetVariableStatus + 1,                          VariableName, NameSize);
   1160       CopyMem (((UINT8 *) (SetVariableStatus + 1)) + NameSize, Data,         DataSize);
   1161 
   1162       REPORT_STATUS_CODE_EX (
   1163         EFI_ERROR_CODE,
   1164         PcdGet32 (PcdErrorCodeSetVariable),
   1165         0,
   1166         NULL,
   1167         &gEdkiiStatusCodeDataTypeVariableGuid,
   1168         SetVariableStatus,
   1169         sizeof (EDKII_SET_VARIABLE_STATUS) + NameSize + DataSize
   1170         );
   1171 
   1172       FreePool (SetVariableStatus);
   1173     }
   1174   }
   1175 
   1176   return Status;
   1177 }
   1178