BdsMisc.c revision 5c08e1173703234cc2913757f237ee916087498a
15c08e1173703234cc2913757f237ee916087498aklu/** @file
25c08e1173703234cc2913757f237ee916087498aklu  Misc BDS library function
35c08e1173703234cc2913757f237ee916087498aklu
45c08e1173703234cc2913757f237ee916087498akluCopyright (c) 2004 - 2008, Intel Corporation. <BR>
55c08e1173703234cc2913757f237ee916087498akluAll rights reserved. This program and the accompanying materials
65c08e1173703234cc2913757f237ee916087498akluare licensed and made available under the terms and conditions of the BSD License
75c08e1173703234cc2913757f237ee916087498akluwhich accompanies this distribution.  The full text of the license may be found at
85c08e1173703234cc2913757f237ee916087498akluhttp://opensource.org/licenses/bsd-license.php
95c08e1173703234cc2913757f237ee916087498aklu
105c08e1173703234cc2913757f237ee916087498akluTHE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
115c08e1173703234cc2913757f237ee916087498akluWITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
125c08e1173703234cc2913757f237ee916087498aklu
135c08e1173703234cc2913757f237ee916087498aklu**/
145c08e1173703234cc2913757f237ee916087498aklu
155c08e1173703234cc2913757f237ee916087498aklu#include "InternalBdsLib.h"
165c08e1173703234cc2913757f237ee916087498aklu
175c08e1173703234cc2913757f237ee916087498aklu
185c08e1173703234cc2913757f237ee916087498aklu#define MAX_STRING_LEN        200
195c08e1173703234cc2913757f237ee916087498aklu
205c08e1173703234cc2913757f237ee916087498akluBOOLEAN   mFeaturerSwitch = TRUE;
215c08e1173703234cc2913757f237ee916087498akluBOOLEAN   mResetRequired  = FALSE;
225c08e1173703234cc2913757f237ee916087498aklu
235c08e1173703234cc2913757f237ee916087498akluextern UINT16 gPlatformBootTimeOutDefault;
245c08e1173703234cc2913757f237ee916087498aklu
255c08e1173703234cc2913757f237ee916087498aklu
265c08e1173703234cc2913757f237ee916087498aklu/**
275c08e1173703234cc2913757f237ee916087498aklu  Return the default value for system Timeout variable.
285c08e1173703234cc2913757f237ee916087498aklu
295c08e1173703234cc2913757f237ee916087498aklu  @return Timeout value.
305c08e1173703234cc2913757f237ee916087498aklu
315c08e1173703234cc2913757f237ee916087498aklu**/
325c08e1173703234cc2913757f237ee916087498akluUINT16
335c08e1173703234cc2913757f237ee916087498akluEFIAPI
345c08e1173703234cc2913757f237ee916087498akluBdsLibGetTimeout (
355c08e1173703234cc2913757f237ee916087498aklu  VOID
365c08e1173703234cc2913757f237ee916087498aklu  )
375c08e1173703234cc2913757f237ee916087498aklu{
385c08e1173703234cc2913757f237ee916087498aklu  UINT16      Timeout;
395c08e1173703234cc2913757f237ee916087498aklu  UINTN       Size;
405c08e1173703234cc2913757f237ee916087498aklu  EFI_STATUS  Status;
415c08e1173703234cc2913757f237ee916087498aklu
425c08e1173703234cc2913757f237ee916087498aklu  //
435c08e1173703234cc2913757f237ee916087498aklu  // Return Timeout variable or 0xffff if no valid
445c08e1173703234cc2913757f237ee916087498aklu  // Timeout variable exists.
455c08e1173703234cc2913757f237ee916087498aklu  //
465c08e1173703234cc2913757f237ee916087498aklu  Size    = sizeof (UINT16);
475c08e1173703234cc2913757f237ee916087498aklu  Status  = gRT->GetVariable (L"Timeout", &gEfiGlobalVariableGuid, NULL, &Size, &Timeout);
485c08e1173703234cc2913757f237ee916087498aklu  if (EFI_ERROR (Status)) {
495c08e1173703234cc2913757f237ee916087498aklu    //
505c08e1173703234cc2913757f237ee916087498aklu    // According to UEFI 2.0 spec, it should treat the Timeout value as 0xffff
515c08e1173703234cc2913757f237ee916087498aklu    // (default value PcdPlatformBootTimeOutDefault) when L"Timeout" variable is not present.
525c08e1173703234cc2913757f237ee916087498aklu    // To make the current EFI Automatic-Test activity possible, platform can choose other value
535c08e1173703234cc2913757f237ee916087498aklu    // for automatic boot when the variable is not present.
545c08e1173703234cc2913757f237ee916087498aklu    //
555c08e1173703234cc2913757f237ee916087498aklu    Timeout = PcdGet16 (PcdPlatformBootTimeOutDefault);
565c08e1173703234cc2913757f237ee916087498aklu  }
575c08e1173703234cc2913757f237ee916087498aklu
585c08e1173703234cc2913757f237ee916087498aklu  return Timeout;
595c08e1173703234cc2913757f237ee916087498aklu}
605c08e1173703234cc2913757f237ee916087498aklu
615c08e1173703234cc2913757f237ee916087498aklu/**
625c08e1173703234cc2913757f237ee916087498aklu  The function will go through the driver option link list, load and start
635c08e1173703234cc2913757f237ee916087498aklu  every driver the driver option device path point to.
645c08e1173703234cc2913757f237ee916087498aklu
655c08e1173703234cc2913757f237ee916087498aklu  @param  BdsDriverLists        The header of the current driver option link list
665c08e1173703234cc2913757f237ee916087498aklu
675c08e1173703234cc2913757f237ee916087498aklu**/
685c08e1173703234cc2913757f237ee916087498akluVOID
695c08e1173703234cc2913757f237ee916087498akluEFIAPI
705c08e1173703234cc2913757f237ee916087498akluBdsLibLoadDrivers (
715c08e1173703234cc2913757f237ee916087498aklu  IN LIST_ENTRY                   *BdsDriverLists
725c08e1173703234cc2913757f237ee916087498aklu  )
735c08e1173703234cc2913757f237ee916087498aklu{
745c08e1173703234cc2913757f237ee916087498aklu  EFI_STATUS                Status;
755c08e1173703234cc2913757f237ee916087498aklu  LIST_ENTRY                *Link;
765c08e1173703234cc2913757f237ee916087498aklu  BDS_COMMON_OPTION         *Option;
775c08e1173703234cc2913757f237ee916087498aklu  EFI_HANDLE                ImageHandle;
785c08e1173703234cc2913757f237ee916087498aklu  EFI_LOADED_IMAGE_PROTOCOL *ImageInfo;
795c08e1173703234cc2913757f237ee916087498aklu  UINTN                     ExitDataSize;
805c08e1173703234cc2913757f237ee916087498aklu  CHAR16                    *ExitData;
815c08e1173703234cc2913757f237ee916087498aklu  BOOLEAN                   ReconnectAll;
825c08e1173703234cc2913757f237ee916087498aklu
835c08e1173703234cc2913757f237ee916087498aklu  ReconnectAll = FALSE;
845c08e1173703234cc2913757f237ee916087498aklu
855c08e1173703234cc2913757f237ee916087498aklu  //
865c08e1173703234cc2913757f237ee916087498aklu  // Process the driver option
875c08e1173703234cc2913757f237ee916087498aklu  //
885c08e1173703234cc2913757f237ee916087498aklu  for (Link = BdsDriverLists->ForwardLink; Link != BdsDriverLists; Link = Link->ForwardLink) {
895c08e1173703234cc2913757f237ee916087498aklu    Option = CR (Link, BDS_COMMON_OPTION, Link, BDS_LOAD_OPTION_SIGNATURE);
905c08e1173703234cc2913757f237ee916087498aklu
915c08e1173703234cc2913757f237ee916087498aklu    //
925c08e1173703234cc2913757f237ee916087498aklu    // If a load option is not marked as LOAD_OPTION_ACTIVE,
935c08e1173703234cc2913757f237ee916087498aklu    // the boot manager will not automatically load the option.
945c08e1173703234cc2913757f237ee916087498aklu    //
955c08e1173703234cc2913757f237ee916087498aklu    if (!IS_LOAD_OPTION_TYPE (Option->Attribute, LOAD_OPTION_ACTIVE)) {
965c08e1173703234cc2913757f237ee916087498aklu      continue;
975c08e1173703234cc2913757f237ee916087498aklu    }
985c08e1173703234cc2913757f237ee916087498aklu
995c08e1173703234cc2913757f237ee916087498aklu    //
1005c08e1173703234cc2913757f237ee916087498aklu    // If a driver load option is marked as LOAD_OPTION_FORCE_RECONNECT,
1015c08e1173703234cc2913757f237ee916087498aklu    // then all of the EFI drivers in the system will be disconnected and
1025c08e1173703234cc2913757f237ee916087498aklu    // reconnected after the last driver load option is processed.
1035c08e1173703234cc2913757f237ee916087498aklu    //
1045c08e1173703234cc2913757f237ee916087498aklu    if (IS_LOAD_OPTION_TYPE (Option->Attribute, LOAD_OPTION_FORCE_RECONNECT)) {
1055c08e1173703234cc2913757f237ee916087498aklu      ReconnectAll = TRUE;
1065c08e1173703234cc2913757f237ee916087498aklu    }
1075c08e1173703234cc2913757f237ee916087498aklu
1085c08e1173703234cc2913757f237ee916087498aklu    //
1095c08e1173703234cc2913757f237ee916087498aklu    // Make sure the driver path is connected.
1105c08e1173703234cc2913757f237ee916087498aklu    //
1115c08e1173703234cc2913757f237ee916087498aklu    BdsLibConnectDevicePath (Option->DevicePath);
1125c08e1173703234cc2913757f237ee916087498aklu
1135c08e1173703234cc2913757f237ee916087498aklu    //
1145c08e1173703234cc2913757f237ee916087498aklu    // Load and start the image that Driver#### describes
1155c08e1173703234cc2913757f237ee916087498aklu    //
1165c08e1173703234cc2913757f237ee916087498aklu    Status = gBS->LoadImage (
1175c08e1173703234cc2913757f237ee916087498aklu                    FALSE,
1185c08e1173703234cc2913757f237ee916087498aklu                    mBdsImageHandle,
1195c08e1173703234cc2913757f237ee916087498aklu                    Option->DevicePath,
1205c08e1173703234cc2913757f237ee916087498aklu                    NULL,
1215c08e1173703234cc2913757f237ee916087498aklu                    0,
1225c08e1173703234cc2913757f237ee916087498aklu                    &ImageHandle
1235c08e1173703234cc2913757f237ee916087498aklu                    );
1245c08e1173703234cc2913757f237ee916087498aklu
1255c08e1173703234cc2913757f237ee916087498aklu    if (!EFI_ERROR (Status)) {
1265c08e1173703234cc2913757f237ee916087498aklu      gBS->HandleProtocol (ImageHandle, &gEfiLoadedImageProtocolGuid, (VOID **) &ImageInfo);
1275c08e1173703234cc2913757f237ee916087498aklu
1285c08e1173703234cc2913757f237ee916087498aklu      //
1295c08e1173703234cc2913757f237ee916087498aklu      // Verify whether this image is a driver, if not,
1305c08e1173703234cc2913757f237ee916087498aklu      // exit it and continue to parse next load option
1315c08e1173703234cc2913757f237ee916087498aklu      //
1325c08e1173703234cc2913757f237ee916087498aklu      if (ImageInfo->ImageCodeType != EfiBootServicesCode && ImageInfo->ImageCodeType != EfiRuntimeServicesCode) {
1335c08e1173703234cc2913757f237ee916087498aklu        gBS->Exit (ImageHandle, EFI_INVALID_PARAMETER, 0, NULL);
1345c08e1173703234cc2913757f237ee916087498aklu        continue;
1355c08e1173703234cc2913757f237ee916087498aklu      }
1365c08e1173703234cc2913757f237ee916087498aklu
1375c08e1173703234cc2913757f237ee916087498aklu      if (Option->LoadOptionsSize != 0) {
1385c08e1173703234cc2913757f237ee916087498aklu        ImageInfo->LoadOptionsSize  = Option->LoadOptionsSize;
1395c08e1173703234cc2913757f237ee916087498aklu        ImageInfo->LoadOptions      = Option->LoadOptions;
1405c08e1173703234cc2913757f237ee916087498aklu      }
1415c08e1173703234cc2913757f237ee916087498aklu      //
1425c08e1173703234cc2913757f237ee916087498aklu      // Before calling the image, enable the Watchdog Timer for
1435c08e1173703234cc2913757f237ee916087498aklu      // the 5 Minute period
1445c08e1173703234cc2913757f237ee916087498aklu      //
1455c08e1173703234cc2913757f237ee916087498aklu      gBS->SetWatchdogTimer (5 * 60, 0x0000, 0x00, NULL);
1465c08e1173703234cc2913757f237ee916087498aklu
1475c08e1173703234cc2913757f237ee916087498aklu      Status = gBS->StartImage (ImageHandle, &ExitDataSize, &ExitData);
1485c08e1173703234cc2913757f237ee916087498aklu      DEBUG ((DEBUG_INFO | DEBUG_LOAD, "Driver Return Status = %r\n", Status));
1495c08e1173703234cc2913757f237ee916087498aklu
1505c08e1173703234cc2913757f237ee916087498aklu      //
1515c08e1173703234cc2913757f237ee916087498aklu      // Clear the Watchdog Timer after the image returns
1525c08e1173703234cc2913757f237ee916087498aklu      //
1535c08e1173703234cc2913757f237ee916087498aklu      gBS->SetWatchdogTimer (0x0000, 0x0000, 0x0000, NULL);
1545c08e1173703234cc2913757f237ee916087498aklu    }
1555c08e1173703234cc2913757f237ee916087498aklu  }
1565c08e1173703234cc2913757f237ee916087498aklu
1575c08e1173703234cc2913757f237ee916087498aklu  //
1585c08e1173703234cc2913757f237ee916087498aklu  // Process the LOAD_OPTION_FORCE_RECONNECT driver option
1595c08e1173703234cc2913757f237ee916087498aklu  //
1605c08e1173703234cc2913757f237ee916087498aklu  if (ReconnectAll) {
1615c08e1173703234cc2913757f237ee916087498aklu    BdsLibDisconnectAllEfi ();
1625c08e1173703234cc2913757f237ee916087498aklu    BdsLibConnectAll ();
1635c08e1173703234cc2913757f237ee916087498aklu  }
1645c08e1173703234cc2913757f237ee916087498aklu
1655c08e1173703234cc2913757f237ee916087498aklu}
1665c08e1173703234cc2913757f237ee916087498aklu
1675c08e1173703234cc2913757f237ee916087498aklu/**
1685c08e1173703234cc2913757f237ee916087498aklu  Get the Option Number that does not used.
1695c08e1173703234cc2913757f237ee916087498aklu  Try to locate the specific option variable one by one utile find a free number.
1705c08e1173703234cc2913757f237ee916087498aklu
1715c08e1173703234cc2913757f237ee916087498aklu  @param  VariableName          Indicate if the boot#### or driver#### option
1725c08e1173703234cc2913757f237ee916087498aklu
1735c08e1173703234cc2913757f237ee916087498aklu  @return The Minimal Free Option Number
1745c08e1173703234cc2913757f237ee916087498aklu
1755c08e1173703234cc2913757f237ee916087498aklu**/
1765c08e1173703234cc2913757f237ee916087498akluUINT16
1775c08e1173703234cc2913757f237ee916087498akluBdsLibGetFreeOptionNumber (
1785c08e1173703234cc2913757f237ee916087498aklu  IN  CHAR16    *VariableName
1795c08e1173703234cc2913757f237ee916087498aklu  )
1805c08e1173703234cc2913757f237ee916087498aklu{
1815c08e1173703234cc2913757f237ee916087498aklu  UINTN         Index;
1825c08e1173703234cc2913757f237ee916087498aklu  CHAR16        StrTemp[10];
1835c08e1173703234cc2913757f237ee916087498aklu  UINT16        *OptionBuffer;
1845c08e1173703234cc2913757f237ee916087498aklu  UINTN         OptionSize;
1855c08e1173703234cc2913757f237ee916087498aklu
1865c08e1173703234cc2913757f237ee916087498aklu  //
1875c08e1173703234cc2913757f237ee916087498aklu  // Try to find the minimum free number from 0, 1, 2, 3....
1885c08e1173703234cc2913757f237ee916087498aklu  //
1895c08e1173703234cc2913757f237ee916087498aklu  Index = 0;
1905c08e1173703234cc2913757f237ee916087498aklu  do {
1915c08e1173703234cc2913757f237ee916087498aklu    if (*VariableName == 'B') {
1925c08e1173703234cc2913757f237ee916087498aklu      UnicodeSPrint (StrTemp, sizeof (StrTemp), L"Boot%04x", Index);
1935c08e1173703234cc2913757f237ee916087498aklu    } else {
1945c08e1173703234cc2913757f237ee916087498aklu      UnicodeSPrint (StrTemp, sizeof (StrTemp), L"Driver%04x", Index);
1955c08e1173703234cc2913757f237ee916087498aklu    }
1965c08e1173703234cc2913757f237ee916087498aklu    //
1975c08e1173703234cc2913757f237ee916087498aklu    // try if the option number is used
1985c08e1173703234cc2913757f237ee916087498aklu    //
1995c08e1173703234cc2913757f237ee916087498aklu    OptionBuffer = BdsLibGetVariableAndSize (
2005c08e1173703234cc2913757f237ee916087498aklu                     StrTemp,
2015c08e1173703234cc2913757f237ee916087498aklu                     &gEfiGlobalVariableGuid,
2025c08e1173703234cc2913757f237ee916087498aklu                     &OptionSize
2035c08e1173703234cc2913757f237ee916087498aklu                     );
2045c08e1173703234cc2913757f237ee916087498aklu    if (OptionBuffer == NULL) {
2055c08e1173703234cc2913757f237ee916087498aklu      break;
2065c08e1173703234cc2913757f237ee916087498aklu    }
2075c08e1173703234cc2913757f237ee916087498aklu    Index++;
2085c08e1173703234cc2913757f237ee916087498aklu  } while (TRUE);
2095c08e1173703234cc2913757f237ee916087498aklu
2105c08e1173703234cc2913757f237ee916087498aklu  return ((UINT16) Index);
2115c08e1173703234cc2913757f237ee916087498aklu}
2125c08e1173703234cc2913757f237ee916087498aklu
2135c08e1173703234cc2913757f237ee916087498aklu
2145c08e1173703234cc2913757f237ee916087498aklu/**
2155c08e1173703234cc2913757f237ee916087498aklu  This function will register the new boot#### or driver#### option base on
2165c08e1173703234cc2913757f237ee916087498aklu  the VariableName. The new registered boot#### or driver#### will be linked
2175c08e1173703234cc2913757f237ee916087498aklu  to BdsOptionList and also update to the VariableName. After the boot#### or
2185c08e1173703234cc2913757f237ee916087498aklu  driver#### updated, the BootOrder or DriverOrder will also be updated.
2195c08e1173703234cc2913757f237ee916087498aklu
2205c08e1173703234cc2913757f237ee916087498aklu  @param  BdsOptionList         The header of the boot#### or driver#### link list
2215c08e1173703234cc2913757f237ee916087498aklu  @param  DevicePath            The device path which the boot#### or driver####
2225c08e1173703234cc2913757f237ee916087498aklu                                option present
2235c08e1173703234cc2913757f237ee916087498aklu  @param  String                The description of the boot#### or driver####
2245c08e1173703234cc2913757f237ee916087498aklu  @param  VariableName          Indicate if the boot#### or driver#### option
2255c08e1173703234cc2913757f237ee916087498aklu
2265c08e1173703234cc2913757f237ee916087498aklu  @retval EFI_SUCCESS           The boot#### or driver#### have been success
2275c08e1173703234cc2913757f237ee916087498aklu                                registered
2285c08e1173703234cc2913757f237ee916087498aklu  @retval EFI_STATUS            Return the status of gRT->SetVariable ().
2295c08e1173703234cc2913757f237ee916087498aklu
2305c08e1173703234cc2913757f237ee916087498aklu**/
2315c08e1173703234cc2913757f237ee916087498akluEFI_STATUS
2325c08e1173703234cc2913757f237ee916087498akluEFIAPI
2335c08e1173703234cc2913757f237ee916087498akluBdsLibRegisterNewOption (
2345c08e1173703234cc2913757f237ee916087498aklu  IN  LIST_ENTRY                     *BdsOptionList,
2355c08e1173703234cc2913757f237ee916087498aklu  IN  EFI_DEVICE_PATH_PROTOCOL       *DevicePath,
2365c08e1173703234cc2913757f237ee916087498aklu  IN  CHAR16                         *String,
2375c08e1173703234cc2913757f237ee916087498aklu  IN  CHAR16                         *VariableName
2385c08e1173703234cc2913757f237ee916087498aklu  )
2395c08e1173703234cc2913757f237ee916087498aklu{
2405c08e1173703234cc2913757f237ee916087498aklu  EFI_STATUS                Status;
2415c08e1173703234cc2913757f237ee916087498aklu  UINTN                     Index;
2425c08e1173703234cc2913757f237ee916087498aklu  UINT16                    RegisterOptionNumber;
2435c08e1173703234cc2913757f237ee916087498aklu  UINT16                    *TempOptionPtr;
2445c08e1173703234cc2913757f237ee916087498aklu  UINTN                     TempOptionSize;
2455c08e1173703234cc2913757f237ee916087498aklu  UINT16                    *OptionOrderPtr;
2465c08e1173703234cc2913757f237ee916087498aklu  VOID                      *OptionPtr;
2475c08e1173703234cc2913757f237ee916087498aklu  UINTN                     OptionSize;
2485c08e1173703234cc2913757f237ee916087498aklu  UINT8                     *TempPtr;
2495c08e1173703234cc2913757f237ee916087498aklu  EFI_DEVICE_PATH_PROTOCOL  *OptionDevicePath;
2505c08e1173703234cc2913757f237ee916087498aklu  CHAR16                    *Description;
2515c08e1173703234cc2913757f237ee916087498aklu  CHAR16                    OptionName[10];
2525c08e1173703234cc2913757f237ee916087498aklu  BOOLEAN                   UpdateDescription;
2535c08e1173703234cc2913757f237ee916087498aklu  UINT16                    BootOrderEntry;
2545c08e1173703234cc2913757f237ee916087498aklu  UINTN                     OrderItemNum;
2555c08e1173703234cc2913757f237ee916087498aklu
2565c08e1173703234cc2913757f237ee916087498aklu
2575c08e1173703234cc2913757f237ee916087498aklu  OptionPtr             = NULL;
2585c08e1173703234cc2913757f237ee916087498aklu  OptionSize            = 0;
2595c08e1173703234cc2913757f237ee916087498aklu  TempPtr               = NULL;
2605c08e1173703234cc2913757f237ee916087498aklu  OptionDevicePath      = NULL;
2615c08e1173703234cc2913757f237ee916087498aklu  Description           = NULL;
2625c08e1173703234cc2913757f237ee916087498aklu  OptionOrderPtr        = NULL;
2635c08e1173703234cc2913757f237ee916087498aklu  UpdateDescription     = FALSE;
2645c08e1173703234cc2913757f237ee916087498aklu  Status                = EFI_SUCCESS;
2655c08e1173703234cc2913757f237ee916087498aklu  ZeroMem (OptionName, sizeof (OptionName));
2665c08e1173703234cc2913757f237ee916087498aklu
2675c08e1173703234cc2913757f237ee916087498aklu  TempOptionSize = 0;
2685c08e1173703234cc2913757f237ee916087498aklu  TempOptionPtr = BdsLibGetVariableAndSize (
2695c08e1173703234cc2913757f237ee916087498aklu                    VariableName,
2705c08e1173703234cc2913757f237ee916087498aklu                    &gEfiGlobalVariableGuid,
2715c08e1173703234cc2913757f237ee916087498aklu                    &TempOptionSize
2725c08e1173703234cc2913757f237ee916087498aklu                    );
2735c08e1173703234cc2913757f237ee916087498aklu  //
2745c08e1173703234cc2913757f237ee916087498aklu  // Compare with current option variable if the previous option is set in global variable.
2755c08e1173703234cc2913757f237ee916087498aklu  //
2765c08e1173703234cc2913757f237ee916087498aklu  for (Index = 0; Index < TempOptionSize / sizeof (UINT16); Index++) {
2775c08e1173703234cc2913757f237ee916087498aklu    //
2785c08e1173703234cc2913757f237ee916087498aklu    // TempOptionPtr must not be NULL if we have non-zero TempOptionSize.
2795c08e1173703234cc2913757f237ee916087498aklu    //
2805c08e1173703234cc2913757f237ee916087498aklu    ASSERT (TempOptionPtr != NULL);
2815c08e1173703234cc2913757f237ee916087498aklu
2825c08e1173703234cc2913757f237ee916087498aklu    if (*VariableName == 'B') {
2835c08e1173703234cc2913757f237ee916087498aklu      UnicodeSPrint (OptionName, sizeof (OptionName), L"Boot%04x", TempOptionPtr[Index]);
2845c08e1173703234cc2913757f237ee916087498aklu    } else {
2855c08e1173703234cc2913757f237ee916087498aklu      UnicodeSPrint (OptionName, sizeof (OptionName), L"Driver%04x", TempOptionPtr[Index]);
2865c08e1173703234cc2913757f237ee916087498aklu    }
2875c08e1173703234cc2913757f237ee916087498aklu
2885c08e1173703234cc2913757f237ee916087498aklu    OptionPtr = BdsLibGetVariableAndSize (
2895c08e1173703234cc2913757f237ee916087498aklu                  OptionName,
2905c08e1173703234cc2913757f237ee916087498aklu                  &gEfiGlobalVariableGuid,
2915c08e1173703234cc2913757f237ee916087498aklu                  &OptionSize
2925c08e1173703234cc2913757f237ee916087498aklu                  );
2935c08e1173703234cc2913757f237ee916087498aklu    if (OptionPtr == NULL) {
2945c08e1173703234cc2913757f237ee916087498aklu      continue;
2955c08e1173703234cc2913757f237ee916087498aklu    }
2965c08e1173703234cc2913757f237ee916087498aklu    TempPtr         =   OptionPtr;
2975c08e1173703234cc2913757f237ee916087498aklu    TempPtr         +=  sizeof (UINT32) + sizeof (UINT16);
2985c08e1173703234cc2913757f237ee916087498aklu    Description     =   (CHAR16 *) TempPtr;
2995c08e1173703234cc2913757f237ee916087498aklu    TempPtr         +=  StrSize ((CHAR16 *) TempPtr);
3005c08e1173703234cc2913757f237ee916087498aklu    OptionDevicePath =  (EFI_DEVICE_PATH_PROTOCOL *) TempPtr;
3015c08e1173703234cc2913757f237ee916087498aklu
3025c08e1173703234cc2913757f237ee916087498aklu    //
3035c08e1173703234cc2913757f237ee916087498aklu    // Notes: the description may will change base on the GetStringToken
3045c08e1173703234cc2913757f237ee916087498aklu    //
3055c08e1173703234cc2913757f237ee916087498aklu    if (CompareMem (OptionDevicePath, DevicePath, GetDevicePathSize (OptionDevicePath)) == 0) {
3065c08e1173703234cc2913757f237ee916087498aklu      if (CompareMem (Description, String, StrSize (Description)) == 0) {
3075c08e1173703234cc2913757f237ee916087498aklu        //
3085c08e1173703234cc2913757f237ee916087498aklu        // Got the option, so just return
3095c08e1173703234cc2913757f237ee916087498aklu        //
3105c08e1173703234cc2913757f237ee916087498aklu        FreePool (OptionPtr);
3115c08e1173703234cc2913757f237ee916087498aklu        FreePool (TempOptionPtr);
3125c08e1173703234cc2913757f237ee916087498aklu        return EFI_SUCCESS;
3135c08e1173703234cc2913757f237ee916087498aklu      } else {
3145c08e1173703234cc2913757f237ee916087498aklu        //
3155c08e1173703234cc2913757f237ee916087498aklu        // Option description changed, need update.
3165c08e1173703234cc2913757f237ee916087498aklu        //
3175c08e1173703234cc2913757f237ee916087498aklu        UpdateDescription = TRUE;
3185c08e1173703234cc2913757f237ee916087498aklu        FreePool (OptionPtr);
3195c08e1173703234cc2913757f237ee916087498aklu        break;
3205c08e1173703234cc2913757f237ee916087498aklu      }
3215c08e1173703234cc2913757f237ee916087498aklu    }
3225c08e1173703234cc2913757f237ee916087498aklu
3235c08e1173703234cc2913757f237ee916087498aklu    FreePool (OptionPtr);
3245c08e1173703234cc2913757f237ee916087498aklu  }
3255c08e1173703234cc2913757f237ee916087498aklu
3265c08e1173703234cc2913757f237ee916087498aklu  OptionSize          = sizeof (UINT32) + sizeof (UINT16) + StrSize (String);
3275c08e1173703234cc2913757f237ee916087498aklu  OptionSize          += GetDevicePathSize (DevicePath);
3285c08e1173703234cc2913757f237ee916087498aklu  OptionPtr           = AllocateZeroPool (OptionSize);
3295c08e1173703234cc2913757f237ee916087498aklu  ASSERT (OptionPtr != NULL);
3305c08e1173703234cc2913757f237ee916087498aklu
3315c08e1173703234cc2913757f237ee916087498aklu  TempPtr             = OptionPtr;
3325c08e1173703234cc2913757f237ee916087498aklu  *(UINT32 *) TempPtr = LOAD_OPTION_ACTIVE;
3335c08e1173703234cc2913757f237ee916087498aklu  TempPtr             += sizeof (UINT32);
3345c08e1173703234cc2913757f237ee916087498aklu  *(UINT16 *) TempPtr = (UINT16) GetDevicePathSize (DevicePath);
3355c08e1173703234cc2913757f237ee916087498aklu  TempPtr             += sizeof (UINT16);
3365c08e1173703234cc2913757f237ee916087498aklu  CopyMem (TempPtr, String, StrSize (String));
3375c08e1173703234cc2913757f237ee916087498aklu  TempPtr             += StrSize (String);
3385c08e1173703234cc2913757f237ee916087498aklu  CopyMem (TempPtr, DevicePath, GetDevicePathSize (DevicePath));
3395c08e1173703234cc2913757f237ee916087498aklu
3405c08e1173703234cc2913757f237ee916087498aklu  if (UpdateDescription) {
3415c08e1173703234cc2913757f237ee916087498aklu    //
3425c08e1173703234cc2913757f237ee916087498aklu    // The number in option#### to be updated.
3435c08e1173703234cc2913757f237ee916087498aklu    // In this case, we must have non-NULL TempOptionPtr.
3445c08e1173703234cc2913757f237ee916087498aklu    //
3455c08e1173703234cc2913757f237ee916087498aklu    ASSERT (TempOptionPtr != NULL);
3465c08e1173703234cc2913757f237ee916087498aklu    RegisterOptionNumber = TempOptionPtr[Index];
3475c08e1173703234cc2913757f237ee916087498aklu  } else {
3485c08e1173703234cc2913757f237ee916087498aklu    //
3495c08e1173703234cc2913757f237ee916087498aklu    // The new option#### number
3505c08e1173703234cc2913757f237ee916087498aklu    //
3515c08e1173703234cc2913757f237ee916087498aklu    RegisterOptionNumber = BdsLibGetFreeOptionNumber(VariableName);
3525c08e1173703234cc2913757f237ee916087498aklu  }
3535c08e1173703234cc2913757f237ee916087498aklu
3545c08e1173703234cc2913757f237ee916087498aklu  if (*VariableName == 'B') {
3555c08e1173703234cc2913757f237ee916087498aklu    UnicodeSPrint (OptionName, sizeof (OptionName), L"Boot%04x", RegisterOptionNumber);
3565c08e1173703234cc2913757f237ee916087498aklu  } else {
3575c08e1173703234cc2913757f237ee916087498aklu    UnicodeSPrint (OptionName, sizeof (OptionName), L"Driver%04x", RegisterOptionNumber);
3585c08e1173703234cc2913757f237ee916087498aklu  }
3595c08e1173703234cc2913757f237ee916087498aklu
3605c08e1173703234cc2913757f237ee916087498aklu  Status = gRT->SetVariable (
3615c08e1173703234cc2913757f237ee916087498aklu                  OptionName,
3625c08e1173703234cc2913757f237ee916087498aklu                  &gEfiGlobalVariableGuid,
3635c08e1173703234cc2913757f237ee916087498aklu                  EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
3645c08e1173703234cc2913757f237ee916087498aklu                  OptionSize,
3655c08e1173703234cc2913757f237ee916087498aklu                  OptionPtr
3665c08e1173703234cc2913757f237ee916087498aklu                  );
3675c08e1173703234cc2913757f237ee916087498aklu  //
3685c08e1173703234cc2913757f237ee916087498aklu  // Return if only need to update a changed description or fail to set option.
3695c08e1173703234cc2913757f237ee916087498aklu  //
3705c08e1173703234cc2913757f237ee916087498aklu  if (EFI_ERROR (Status) || UpdateDescription) {
3715c08e1173703234cc2913757f237ee916087498aklu    FreePool (OptionPtr);
3725c08e1173703234cc2913757f237ee916087498aklu    if (TempOptionPtr != NULL) {
3735c08e1173703234cc2913757f237ee916087498aklu      FreePool (TempOptionPtr);
3745c08e1173703234cc2913757f237ee916087498aklu    }
3755c08e1173703234cc2913757f237ee916087498aklu    return Status;
3765c08e1173703234cc2913757f237ee916087498aklu  }
3775c08e1173703234cc2913757f237ee916087498aklu
3785c08e1173703234cc2913757f237ee916087498aklu  FreePool (OptionPtr);
3795c08e1173703234cc2913757f237ee916087498aklu
3805c08e1173703234cc2913757f237ee916087498aklu  //
3815c08e1173703234cc2913757f237ee916087498aklu  // Update the option order variable
3825c08e1173703234cc2913757f237ee916087498aklu  //
3835c08e1173703234cc2913757f237ee916087498aklu
3845c08e1173703234cc2913757f237ee916087498aklu  //
3855c08e1173703234cc2913757f237ee916087498aklu  // If no option order
3865c08e1173703234cc2913757f237ee916087498aklu  //
3875c08e1173703234cc2913757f237ee916087498aklu  if (TempOptionSize == 0) {
3885c08e1173703234cc2913757f237ee916087498aklu    BootOrderEntry = 0;
3895c08e1173703234cc2913757f237ee916087498aklu    Status = gRT->SetVariable (
3905c08e1173703234cc2913757f237ee916087498aklu                    VariableName,
3915c08e1173703234cc2913757f237ee916087498aklu                    &gEfiGlobalVariableGuid,
3925c08e1173703234cc2913757f237ee916087498aklu                    EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
3935c08e1173703234cc2913757f237ee916087498aklu                    sizeof (UINT16),
3945c08e1173703234cc2913757f237ee916087498aklu                    &BootOrderEntry
3955c08e1173703234cc2913757f237ee916087498aklu                    );
3965c08e1173703234cc2913757f237ee916087498aklu    if (TempOptionPtr != NULL) {
3975c08e1173703234cc2913757f237ee916087498aklu      FreePool (TempOptionPtr);
3985c08e1173703234cc2913757f237ee916087498aklu    }
3995c08e1173703234cc2913757f237ee916087498aklu    return Status;
4005c08e1173703234cc2913757f237ee916087498aklu  }
4015c08e1173703234cc2913757f237ee916087498aklu
4025c08e1173703234cc2913757f237ee916087498aklu  //
4035c08e1173703234cc2913757f237ee916087498aklu  // TempOptionPtr must not be NULL if TempOptionSize is not zero.
4045c08e1173703234cc2913757f237ee916087498aklu  //
4055c08e1173703234cc2913757f237ee916087498aklu  ASSERT (TempOptionPtr != NULL);
4065c08e1173703234cc2913757f237ee916087498aklu  //
4075c08e1173703234cc2913757f237ee916087498aklu  // Append the new option number to the original option order
4085c08e1173703234cc2913757f237ee916087498aklu  //
4095c08e1173703234cc2913757f237ee916087498aklu  OrderItemNum = (TempOptionSize / sizeof (UINT16)) + 1 ;
4105c08e1173703234cc2913757f237ee916087498aklu  OptionOrderPtr = AllocateZeroPool ( OrderItemNum * sizeof (UINT16));
4115c08e1173703234cc2913757f237ee916087498aklu  ASSERT (OptionOrderPtr!= NULL);
4125c08e1173703234cc2913757f237ee916087498aklu  CopyMem (OptionOrderPtr, TempOptionPtr, (OrderItemNum - 1) * sizeof (UINT16));
4135c08e1173703234cc2913757f237ee916087498aklu
4145c08e1173703234cc2913757f237ee916087498aklu  OptionOrderPtr[Index] = RegisterOptionNumber;
4155c08e1173703234cc2913757f237ee916087498aklu
4165c08e1173703234cc2913757f237ee916087498aklu  Status = gRT->SetVariable (
4175c08e1173703234cc2913757f237ee916087498aklu                  VariableName,
4185c08e1173703234cc2913757f237ee916087498aklu                  &gEfiGlobalVariableGuid,
4195c08e1173703234cc2913757f237ee916087498aklu                  EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
4205c08e1173703234cc2913757f237ee916087498aklu                  OrderItemNum * sizeof (UINT16),
4215c08e1173703234cc2913757f237ee916087498aklu                  OptionOrderPtr
4225c08e1173703234cc2913757f237ee916087498aklu                  );
4235c08e1173703234cc2913757f237ee916087498aklu  FreePool (TempOptionPtr);
4245c08e1173703234cc2913757f237ee916087498aklu  FreePool (OptionOrderPtr);
4255c08e1173703234cc2913757f237ee916087498aklu
4265c08e1173703234cc2913757f237ee916087498aklu  return Status;
4275c08e1173703234cc2913757f237ee916087498aklu}
4285c08e1173703234cc2913757f237ee916087498aklu
4295c08e1173703234cc2913757f237ee916087498aklu
4305c08e1173703234cc2913757f237ee916087498aklu/**
4315c08e1173703234cc2913757f237ee916087498aklu  Build the boot#### or driver#### option from the VariableName, the
4325c08e1173703234cc2913757f237ee916087498aklu  build boot#### or driver#### will also be linked to BdsCommonOptionList.
4335c08e1173703234cc2913757f237ee916087498aklu
4345c08e1173703234cc2913757f237ee916087498aklu  @param  BdsCommonOptionList   The header of the boot#### or driver#### option
4355c08e1173703234cc2913757f237ee916087498aklu                                link list
4365c08e1173703234cc2913757f237ee916087498aklu  @param  VariableName          EFI Variable name indicate if it is boot#### or
4375c08e1173703234cc2913757f237ee916087498aklu                                driver####
4385c08e1173703234cc2913757f237ee916087498aklu
4395c08e1173703234cc2913757f237ee916087498aklu  @retval BDS_COMMON_OPTION     Get the option just been created
4405c08e1173703234cc2913757f237ee916087498aklu  @retval NULL                  Failed to get the new option
4415c08e1173703234cc2913757f237ee916087498aklu
4425c08e1173703234cc2913757f237ee916087498aklu**/
4435c08e1173703234cc2913757f237ee916087498akluBDS_COMMON_OPTION *
4445c08e1173703234cc2913757f237ee916087498akluEFIAPI
4455c08e1173703234cc2913757f237ee916087498akluBdsLibVariableToOption (
4465c08e1173703234cc2913757f237ee916087498aklu  IN OUT LIST_ENTRY                   *BdsCommonOptionList,
4475c08e1173703234cc2913757f237ee916087498aklu  IN  CHAR16                          *VariableName
4485c08e1173703234cc2913757f237ee916087498aklu  )
4495c08e1173703234cc2913757f237ee916087498aklu{
4505c08e1173703234cc2913757f237ee916087498aklu  UINT32                    Attribute;
4515c08e1173703234cc2913757f237ee916087498aklu  UINT16                    FilePathSize;
4525c08e1173703234cc2913757f237ee916087498aklu  UINT8                     *Variable;
4535c08e1173703234cc2913757f237ee916087498aklu  UINT8                     *TempPtr;
4545c08e1173703234cc2913757f237ee916087498aklu  UINTN                     VariableSize;
4555c08e1173703234cc2913757f237ee916087498aklu  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
4565c08e1173703234cc2913757f237ee916087498aklu  BDS_COMMON_OPTION         *Option;
4575c08e1173703234cc2913757f237ee916087498aklu  VOID                      *LoadOptions;
4585c08e1173703234cc2913757f237ee916087498aklu  UINT32                    LoadOptionsSize;
4595c08e1173703234cc2913757f237ee916087498aklu  CHAR16                    *Description;
4605c08e1173703234cc2913757f237ee916087498aklu  UINT8                     NumOff;
4615c08e1173703234cc2913757f237ee916087498aklu  //
4625c08e1173703234cc2913757f237ee916087498aklu  // Read the variable. We will never free this data.
4635c08e1173703234cc2913757f237ee916087498aklu  //
4645c08e1173703234cc2913757f237ee916087498aklu  Variable = BdsLibGetVariableAndSize (
4655c08e1173703234cc2913757f237ee916087498aklu              VariableName,
4665c08e1173703234cc2913757f237ee916087498aklu              &gEfiGlobalVariableGuid,
4675c08e1173703234cc2913757f237ee916087498aklu              &VariableSize
4685c08e1173703234cc2913757f237ee916087498aklu              );
4695c08e1173703234cc2913757f237ee916087498aklu  if (Variable == NULL) {
4705c08e1173703234cc2913757f237ee916087498aklu    return NULL;
4715c08e1173703234cc2913757f237ee916087498aklu  }
4725c08e1173703234cc2913757f237ee916087498aklu  //
4735c08e1173703234cc2913757f237ee916087498aklu  // Notes: careful defined the variable of Boot#### or
4745c08e1173703234cc2913757f237ee916087498aklu  // Driver####, consider use some macro to abstract the code
4755c08e1173703234cc2913757f237ee916087498aklu  //
4765c08e1173703234cc2913757f237ee916087498aklu  //
4775c08e1173703234cc2913757f237ee916087498aklu  // Get the option attribute
4785c08e1173703234cc2913757f237ee916087498aklu  //
4795c08e1173703234cc2913757f237ee916087498aklu  TempPtr   =  Variable;
4805c08e1173703234cc2913757f237ee916087498aklu  Attribute =  *(UINT32 *) Variable;
4815c08e1173703234cc2913757f237ee916087498aklu  TempPtr   += sizeof (UINT32);
4825c08e1173703234cc2913757f237ee916087498aklu
4835c08e1173703234cc2913757f237ee916087498aklu  //
4845c08e1173703234cc2913757f237ee916087498aklu  // Get the option's device path size
4855c08e1173703234cc2913757f237ee916087498aklu  //
4865c08e1173703234cc2913757f237ee916087498aklu  FilePathSize =  *(UINT16 *) TempPtr;
4875c08e1173703234cc2913757f237ee916087498aklu  TempPtr      += sizeof (UINT16);
4885c08e1173703234cc2913757f237ee916087498aklu
4895c08e1173703234cc2913757f237ee916087498aklu  //
4905c08e1173703234cc2913757f237ee916087498aklu  // Get the option's description string
4915c08e1173703234cc2913757f237ee916087498aklu  //
4925c08e1173703234cc2913757f237ee916087498aklu  Description = (CHAR16 *) TempPtr;
4935c08e1173703234cc2913757f237ee916087498aklu
4945c08e1173703234cc2913757f237ee916087498aklu  //
4955c08e1173703234cc2913757f237ee916087498aklu  // Get the option's description string size
4965c08e1173703234cc2913757f237ee916087498aklu  //
4975c08e1173703234cc2913757f237ee916087498aklu  TempPtr     += StrSize ((CHAR16 *) TempPtr);
4985c08e1173703234cc2913757f237ee916087498aklu
4995c08e1173703234cc2913757f237ee916087498aklu  //
5005c08e1173703234cc2913757f237ee916087498aklu  // Get the option's device path
5015c08e1173703234cc2913757f237ee916087498aklu  //
5025c08e1173703234cc2913757f237ee916087498aklu  DevicePath =  (EFI_DEVICE_PATH_PROTOCOL *) TempPtr;
5035c08e1173703234cc2913757f237ee916087498aklu  TempPtr    += FilePathSize;
5045c08e1173703234cc2913757f237ee916087498aklu
5055c08e1173703234cc2913757f237ee916087498aklu  LoadOptions     = TempPtr;
5065c08e1173703234cc2913757f237ee916087498aklu  LoadOptionsSize = (UINT32) (VariableSize - (UINTN) (TempPtr - Variable));
5075c08e1173703234cc2913757f237ee916087498aklu
5085c08e1173703234cc2913757f237ee916087498aklu  //
5095c08e1173703234cc2913757f237ee916087498aklu  // The Console variables may have multiple device paths, so make
5105c08e1173703234cc2913757f237ee916087498aklu  // an Entry for each one.
5115c08e1173703234cc2913757f237ee916087498aklu  //
5125c08e1173703234cc2913757f237ee916087498aklu  Option = AllocateZeroPool (sizeof (BDS_COMMON_OPTION));
5135c08e1173703234cc2913757f237ee916087498aklu  if (Option == NULL) {
5145c08e1173703234cc2913757f237ee916087498aklu    return NULL;
5155c08e1173703234cc2913757f237ee916087498aklu  }
5165c08e1173703234cc2913757f237ee916087498aklu
5175c08e1173703234cc2913757f237ee916087498aklu  Option->Signature   = BDS_LOAD_OPTION_SIGNATURE;
5185c08e1173703234cc2913757f237ee916087498aklu  Option->DevicePath  = AllocateZeroPool (GetDevicePathSize (DevicePath));
5195c08e1173703234cc2913757f237ee916087498aklu  ASSERT(Option->DevicePath != NULL);
5205c08e1173703234cc2913757f237ee916087498aklu  CopyMem (Option->DevicePath, DevicePath, GetDevicePathSize (DevicePath));
5215c08e1173703234cc2913757f237ee916087498aklu
5225c08e1173703234cc2913757f237ee916087498aklu  Option->Attribute   = Attribute;
5235c08e1173703234cc2913757f237ee916087498aklu  Option->Description = AllocateZeroPool (StrSize (Description));
5245c08e1173703234cc2913757f237ee916087498aklu  ASSERT(Option->Description != NULL);
5255c08e1173703234cc2913757f237ee916087498aklu  CopyMem (Option->Description, Description, StrSize (Description));
5265c08e1173703234cc2913757f237ee916087498aklu
5275c08e1173703234cc2913757f237ee916087498aklu  Option->LoadOptions = AllocateZeroPool (LoadOptionsSize);
5285c08e1173703234cc2913757f237ee916087498aklu  ASSERT(Option->LoadOptions != NULL);
5295c08e1173703234cc2913757f237ee916087498aklu  CopyMem (Option->LoadOptions, LoadOptions, LoadOptionsSize);
5305c08e1173703234cc2913757f237ee916087498aklu  Option->LoadOptionsSize = LoadOptionsSize;
5315c08e1173703234cc2913757f237ee916087498aklu
5325c08e1173703234cc2913757f237ee916087498aklu  //
5335c08e1173703234cc2913757f237ee916087498aklu  // Get the value from VariableName Unicode string
5345c08e1173703234cc2913757f237ee916087498aklu  // since the ISO standard assumes ASCII equivalent abbreviations, we can be safe in converting this
5355c08e1173703234cc2913757f237ee916087498aklu  // Unicode stream to ASCII without any loss in meaning.
5365c08e1173703234cc2913757f237ee916087498aklu  //
5375c08e1173703234cc2913757f237ee916087498aklu  if (*VariableName == 'B') {
5385c08e1173703234cc2913757f237ee916087498aklu    NumOff = sizeof (L"Boot")/sizeof(CHAR16) -1 ;
5395c08e1173703234cc2913757f237ee916087498aklu    Option->BootCurrent = (UINT16) ((VariableName[NumOff]  -'0') * 0x1000);
5405c08e1173703234cc2913757f237ee916087498aklu    Option->BootCurrent = (UINT16) (Option->BootCurrent + ((VariableName[NumOff+1]-'0') * 0x100));
5415c08e1173703234cc2913757f237ee916087498aklu    Option->BootCurrent = (UINT16) (Option->BootCurrent +  ((VariableName[NumOff+2]-'0') * 0x10));
5425c08e1173703234cc2913757f237ee916087498aklu    Option->BootCurrent = (UINT16) (Option->BootCurrent + ((VariableName[NumOff+3]-'0')));
5435c08e1173703234cc2913757f237ee916087498aklu  }
5445c08e1173703234cc2913757f237ee916087498aklu  //
5455c08e1173703234cc2913757f237ee916087498aklu  // Insert active entry to BdsDeviceList
5465c08e1173703234cc2913757f237ee916087498aklu  //
5475c08e1173703234cc2913757f237ee916087498aklu  if ((Option->Attribute & LOAD_OPTION_ACTIVE) == LOAD_OPTION_ACTIVE) {
5485c08e1173703234cc2913757f237ee916087498aklu    InsertTailList (BdsCommonOptionList, &Option->Link);
5495c08e1173703234cc2913757f237ee916087498aklu    FreePool (Variable);
5505c08e1173703234cc2913757f237ee916087498aklu    return Option;
5515c08e1173703234cc2913757f237ee916087498aklu  }
5525c08e1173703234cc2913757f237ee916087498aklu
5535c08e1173703234cc2913757f237ee916087498aklu  FreePool (Variable);
5545c08e1173703234cc2913757f237ee916087498aklu  FreePool (Option);
5555c08e1173703234cc2913757f237ee916087498aklu  return NULL;
5565c08e1173703234cc2913757f237ee916087498aklu
5575c08e1173703234cc2913757f237ee916087498aklu}
5585c08e1173703234cc2913757f237ee916087498aklu
5595c08e1173703234cc2913757f237ee916087498aklu/**
5605c08e1173703234cc2913757f237ee916087498aklu  Process BootOrder, or DriverOrder variables, by calling
5615c08e1173703234cc2913757f237ee916087498aklu  BdsLibVariableToOption () for each UINT16 in the variables.
5625c08e1173703234cc2913757f237ee916087498aklu
5635c08e1173703234cc2913757f237ee916087498aklu  @param  BdsCommonOptionList   The header of the option list base on variable
5645c08e1173703234cc2913757f237ee916087498aklu                                VariableName
5655c08e1173703234cc2913757f237ee916087498aklu  @param  VariableName          EFI Variable name indicate the BootOrder or
5665c08e1173703234cc2913757f237ee916087498aklu                                DriverOrder
5675c08e1173703234cc2913757f237ee916087498aklu
5685c08e1173703234cc2913757f237ee916087498aklu  @retval EFI_SUCCESS           Success create the boot option or driver option
5695c08e1173703234cc2913757f237ee916087498aklu                                list
5705c08e1173703234cc2913757f237ee916087498aklu  @retval EFI_OUT_OF_RESOURCES  Failed to get the boot option or driver option list
5715c08e1173703234cc2913757f237ee916087498aklu
5725c08e1173703234cc2913757f237ee916087498aklu**/
5735c08e1173703234cc2913757f237ee916087498akluEFI_STATUS
5745c08e1173703234cc2913757f237ee916087498akluEFIAPI
5755c08e1173703234cc2913757f237ee916087498akluBdsLibBuildOptionFromVar (
5765c08e1173703234cc2913757f237ee916087498aklu  IN  LIST_ENTRY                      *BdsCommonOptionList,
5775c08e1173703234cc2913757f237ee916087498aklu  IN  CHAR16                          *VariableName
5785c08e1173703234cc2913757f237ee916087498aklu  )
5795c08e1173703234cc2913757f237ee916087498aklu{
5805c08e1173703234cc2913757f237ee916087498aklu  UINT16            *OptionOrder;
5815c08e1173703234cc2913757f237ee916087498aklu  UINTN             OptionOrderSize;
5825c08e1173703234cc2913757f237ee916087498aklu  UINTN             Index;
5835c08e1173703234cc2913757f237ee916087498aklu  BDS_COMMON_OPTION *Option;
5845c08e1173703234cc2913757f237ee916087498aklu  CHAR16            OptionName[20];
5855c08e1173703234cc2913757f237ee916087498aklu
5865c08e1173703234cc2913757f237ee916087498aklu  //
5875c08e1173703234cc2913757f237ee916087498aklu  // Zero Buffer in order to get all BOOT#### variables
5885c08e1173703234cc2913757f237ee916087498aklu  //
5895c08e1173703234cc2913757f237ee916087498aklu  ZeroMem (OptionName, sizeof (OptionName));
5905c08e1173703234cc2913757f237ee916087498aklu
5915c08e1173703234cc2913757f237ee916087498aklu  //
5925c08e1173703234cc2913757f237ee916087498aklu  // Read the BootOrder, or DriverOrder variable.
5935c08e1173703234cc2913757f237ee916087498aklu  //
5945c08e1173703234cc2913757f237ee916087498aklu  OptionOrder = BdsLibGetVariableAndSize (
5955c08e1173703234cc2913757f237ee916087498aklu                  VariableName,
5965c08e1173703234cc2913757f237ee916087498aklu                  &gEfiGlobalVariableGuid,
5975c08e1173703234cc2913757f237ee916087498aklu                  &OptionOrderSize
5985c08e1173703234cc2913757f237ee916087498aklu                  );
5995c08e1173703234cc2913757f237ee916087498aklu  if (OptionOrder == NULL) {
6005c08e1173703234cc2913757f237ee916087498aklu    return EFI_OUT_OF_RESOURCES;
6015c08e1173703234cc2913757f237ee916087498aklu  }
6025c08e1173703234cc2913757f237ee916087498aklu
6035c08e1173703234cc2913757f237ee916087498aklu  for (Index = 0; Index < OptionOrderSize / sizeof (UINT16); Index++) {
6045c08e1173703234cc2913757f237ee916087498aklu    if (*VariableName == 'B') {
6055c08e1173703234cc2913757f237ee916087498aklu      UnicodeSPrint (OptionName, sizeof (OptionName), L"Boot%04x", OptionOrder[Index]);
6065c08e1173703234cc2913757f237ee916087498aklu    } else {
6075c08e1173703234cc2913757f237ee916087498aklu      UnicodeSPrint (OptionName, sizeof (OptionName), L"Driver%04x", OptionOrder[Index]);
6085c08e1173703234cc2913757f237ee916087498aklu    }
6095c08e1173703234cc2913757f237ee916087498aklu
6105c08e1173703234cc2913757f237ee916087498aklu    Option              = BdsLibVariableToOption (BdsCommonOptionList, OptionName);
6115c08e1173703234cc2913757f237ee916087498aklu    ASSERT (Option != NULL);
6125c08e1173703234cc2913757f237ee916087498aklu    Option->BootCurrent = OptionOrder[Index];
6135c08e1173703234cc2913757f237ee916087498aklu
6145c08e1173703234cc2913757f237ee916087498aklu  }
6155c08e1173703234cc2913757f237ee916087498aklu
6165c08e1173703234cc2913757f237ee916087498aklu  FreePool (OptionOrder);
6175c08e1173703234cc2913757f237ee916087498aklu
6185c08e1173703234cc2913757f237ee916087498aklu  return EFI_SUCCESS;
6195c08e1173703234cc2913757f237ee916087498aklu}
6205c08e1173703234cc2913757f237ee916087498aklu
6215c08e1173703234cc2913757f237ee916087498aklu/**
6225c08e1173703234cc2913757f237ee916087498aklu  Get boot mode by looking up configuration table and parsing HOB list
6235c08e1173703234cc2913757f237ee916087498aklu
6245c08e1173703234cc2913757f237ee916087498aklu  @param  BootMode              Boot mode from PEI handoff HOB.
6255c08e1173703234cc2913757f237ee916087498aklu
6265c08e1173703234cc2913757f237ee916087498aklu  @retval EFI_SUCCESS           Successfully get boot mode
6275c08e1173703234cc2913757f237ee916087498aklu
6285c08e1173703234cc2913757f237ee916087498aklu**/
6295c08e1173703234cc2913757f237ee916087498akluEFI_STATUS
6305c08e1173703234cc2913757f237ee916087498akluEFIAPI
6315c08e1173703234cc2913757f237ee916087498akluBdsLibGetBootMode (
6325c08e1173703234cc2913757f237ee916087498aklu  OUT EFI_BOOT_MODE       *BootMode
6335c08e1173703234cc2913757f237ee916087498aklu  )
6345c08e1173703234cc2913757f237ee916087498aklu{
6355c08e1173703234cc2913757f237ee916087498aklu  *BootMode = GetBootModeHob ();
6365c08e1173703234cc2913757f237ee916087498aklu
6375c08e1173703234cc2913757f237ee916087498aklu  return EFI_SUCCESS;
6385c08e1173703234cc2913757f237ee916087498aklu}
6395c08e1173703234cc2913757f237ee916087498aklu
6405c08e1173703234cc2913757f237ee916087498aklu/**
6415c08e1173703234cc2913757f237ee916087498aklu  Read the EFI variable (VendorGuid/Name) and return a dynamically allocated
6425c08e1173703234cc2913757f237ee916087498aklu  buffer, and the size of the buffer. If failure return NULL.
6435c08e1173703234cc2913757f237ee916087498aklu
6445c08e1173703234cc2913757f237ee916087498aklu  @param  Name                  String part of EFI variable name
6455c08e1173703234cc2913757f237ee916087498aklu  @param  VendorGuid            GUID part of EFI variable name
6465c08e1173703234cc2913757f237ee916087498aklu  @param  VariableSize          Returns the size of the EFI variable that was read
6475c08e1173703234cc2913757f237ee916087498aklu
6485c08e1173703234cc2913757f237ee916087498aklu  @return                       Dynamically allocated memory that contains a copy of the EFI variable
6495c08e1173703234cc2913757f237ee916087498aklu                                Caller is responsible freeing the buffer.
6505c08e1173703234cc2913757f237ee916087498aklu  @retval NULL                  Variable was not read
6515c08e1173703234cc2913757f237ee916087498aklu
6525c08e1173703234cc2913757f237ee916087498aklu**/
6535c08e1173703234cc2913757f237ee916087498akluVOID *
6545c08e1173703234cc2913757f237ee916087498akluEFIAPI
6555c08e1173703234cc2913757f237ee916087498akluBdsLibGetVariableAndSize (
6565c08e1173703234cc2913757f237ee916087498aklu  IN  CHAR16              *Name,
6575c08e1173703234cc2913757f237ee916087498aklu  IN  EFI_GUID            *VendorGuid,
6585c08e1173703234cc2913757f237ee916087498aklu  OUT UINTN               *VariableSize
6595c08e1173703234cc2913757f237ee916087498aklu  )
6605c08e1173703234cc2913757f237ee916087498aklu{
6615c08e1173703234cc2913757f237ee916087498aklu  EFI_STATUS  Status;
6625c08e1173703234cc2913757f237ee916087498aklu  UINTN       BufferSize;
6635c08e1173703234cc2913757f237ee916087498aklu  VOID        *Buffer;
6645c08e1173703234cc2913757f237ee916087498aklu
6655c08e1173703234cc2913757f237ee916087498aklu  Buffer = NULL;
6665c08e1173703234cc2913757f237ee916087498aklu
6675c08e1173703234cc2913757f237ee916087498aklu  //
6685c08e1173703234cc2913757f237ee916087498aklu  // Pass in a zero size buffer to find the required buffer size.
6695c08e1173703234cc2913757f237ee916087498aklu  //
6705c08e1173703234cc2913757f237ee916087498aklu  BufferSize  = 0;
6715c08e1173703234cc2913757f237ee916087498aklu  Status      = gRT->GetVariable (Name, VendorGuid, NULL, &BufferSize, Buffer);
6725c08e1173703234cc2913757f237ee916087498aklu  if (Status == EFI_BUFFER_TOO_SMALL) {
6735c08e1173703234cc2913757f237ee916087498aklu    //
6745c08e1173703234cc2913757f237ee916087498aklu    // Allocate the buffer to return
6755c08e1173703234cc2913757f237ee916087498aklu    //
6765c08e1173703234cc2913757f237ee916087498aklu    Buffer = AllocateZeroPool (BufferSize);
6775c08e1173703234cc2913757f237ee916087498aklu    if (Buffer == NULL) {
6785c08e1173703234cc2913757f237ee916087498aklu      return NULL;
6795c08e1173703234cc2913757f237ee916087498aklu    }
6805c08e1173703234cc2913757f237ee916087498aklu    //
6815c08e1173703234cc2913757f237ee916087498aklu    // Read variable into the allocated buffer.
6825c08e1173703234cc2913757f237ee916087498aklu    //
6835c08e1173703234cc2913757f237ee916087498aklu    Status = gRT->GetVariable (Name, VendorGuid, NULL, &BufferSize, Buffer);
6845c08e1173703234cc2913757f237ee916087498aklu    if (EFI_ERROR (Status)) {
6855c08e1173703234cc2913757f237ee916087498aklu      BufferSize = 0;
6865c08e1173703234cc2913757f237ee916087498aklu    }
6875c08e1173703234cc2913757f237ee916087498aklu  }
6885c08e1173703234cc2913757f237ee916087498aklu
6895c08e1173703234cc2913757f237ee916087498aklu  *VariableSize = BufferSize;
6905c08e1173703234cc2913757f237ee916087498aklu  return Buffer;
6915c08e1173703234cc2913757f237ee916087498aklu}
6925c08e1173703234cc2913757f237ee916087498aklu
6935c08e1173703234cc2913757f237ee916087498aklu/**
6945c08e1173703234cc2913757f237ee916087498aklu  Delete the instance in Multi which matches partly with Single instance
6955c08e1173703234cc2913757f237ee916087498aklu
6965c08e1173703234cc2913757f237ee916087498aklu  @param  Multi                 A pointer to a multi-instance device path data
6975c08e1173703234cc2913757f237ee916087498aklu                                structure.
6985c08e1173703234cc2913757f237ee916087498aklu  @param  Single                A pointer to a single-instance device path data
6995c08e1173703234cc2913757f237ee916087498aklu                                structure.
7005c08e1173703234cc2913757f237ee916087498aklu
7015c08e1173703234cc2913757f237ee916087498aklu  @return This function will remove the device path instances in Multi which partly
7025c08e1173703234cc2913757f237ee916087498aklu          match with the Single, and return the result device path. If there is no
7035c08e1173703234cc2913757f237ee916087498aklu          remaining device path as a result, this function will return NULL.
7045c08e1173703234cc2913757f237ee916087498aklu
7055c08e1173703234cc2913757f237ee916087498aklu**/
7065c08e1173703234cc2913757f237ee916087498akluEFI_DEVICE_PATH_PROTOCOL *
7075c08e1173703234cc2913757f237ee916087498akluEFIAPI
7085c08e1173703234cc2913757f237ee916087498akluBdsLibDelPartMatchInstance (
7095c08e1173703234cc2913757f237ee916087498aklu  IN     EFI_DEVICE_PATH_PROTOCOL  *Multi,
7105c08e1173703234cc2913757f237ee916087498aklu  IN     EFI_DEVICE_PATH_PROTOCOL  *Single
7115c08e1173703234cc2913757f237ee916087498aklu  )
7125c08e1173703234cc2913757f237ee916087498aklu{
7135c08e1173703234cc2913757f237ee916087498aklu  EFI_DEVICE_PATH_PROTOCOL  *Instance;
7145c08e1173703234cc2913757f237ee916087498aklu  EFI_DEVICE_PATH_PROTOCOL  *NewDevicePath;
7155c08e1173703234cc2913757f237ee916087498aklu  EFI_DEVICE_PATH_PROTOCOL  *TempNewDevicePath;
7165c08e1173703234cc2913757f237ee916087498aklu  UINTN                     InstanceSize;
7175c08e1173703234cc2913757f237ee916087498aklu  UINTN                     SingleDpSize;
7185c08e1173703234cc2913757f237ee916087498aklu  UINTN                     Size;
7195c08e1173703234cc2913757f237ee916087498aklu
7205c08e1173703234cc2913757f237ee916087498aklu  NewDevicePath     = NULL;
7215c08e1173703234cc2913757f237ee916087498aklu  TempNewDevicePath = NULL;
7225c08e1173703234cc2913757f237ee916087498aklu
7235c08e1173703234cc2913757f237ee916087498aklu  if (Multi == NULL || Single == NULL) {
7245c08e1173703234cc2913757f237ee916087498aklu    return Multi;
7255c08e1173703234cc2913757f237ee916087498aklu  }
7265c08e1173703234cc2913757f237ee916087498aklu
7275c08e1173703234cc2913757f237ee916087498aklu  Instance        =  GetNextDevicePathInstance (&Multi, &InstanceSize);
7285c08e1173703234cc2913757f237ee916087498aklu  SingleDpSize    =  GetDevicePathSize (Single) - END_DEVICE_PATH_LENGTH;
7295c08e1173703234cc2913757f237ee916087498aklu  InstanceSize    -= END_DEVICE_PATH_LENGTH;
7305c08e1173703234cc2913757f237ee916087498aklu
7315c08e1173703234cc2913757f237ee916087498aklu  while (Instance != NULL) {
7325c08e1173703234cc2913757f237ee916087498aklu
7335c08e1173703234cc2913757f237ee916087498aklu    Size = (SingleDpSize < InstanceSize) ? SingleDpSize : InstanceSize;
7345c08e1173703234cc2913757f237ee916087498aklu
7355c08e1173703234cc2913757f237ee916087498aklu    if ((CompareMem (Instance, Single, Size) != 0)) {
7365c08e1173703234cc2913757f237ee916087498aklu      //
7375c08e1173703234cc2913757f237ee916087498aklu      // Append the device path instance which does not match with Single
7385c08e1173703234cc2913757f237ee916087498aklu      //
7395c08e1173703234cc2913757f237ee916087498aklu      TempNewDevicePath = NewDevicePath;
7405c08e1173703234cc2913757f237ee916087498aklu      NewDevicePath = AppendDevicePathInstance (NewDevicePath, Instance);
7415c08e1173703234cc2913757f237ee916087498aklu      if (TempNewDevicePath != NULL) {
7425c08e1173703234cc2913757f237ee916087498aklu        FreePool(TempNewDevicePath);
7435c08e1173703234cc2913757f237ee916087498aklu      }
7445c08e1173703234cc2913757f237ee916087498aklu    }
7455c08e1173703234cc2913757f237ee916087498aklu    FreePool(Instance);
7465c08e1173703234cc2913757f237ee916087498aklu    Instance = GetNextDevicePathInstance (&Multi, &InstanceSize);
7475c08e1173703234cc2913757f237ee916087498aklu    InstanceSize  -= END_DEVICE_PATH_LENGTH;
7485c08e1173703234cc2913757f237ee916087498aklu  }
7495c08e1173703234cc2913757f237ee916087498aklu
7505c08e1173703234cc2913757f237ee916087498aklu  return NewDevicePath;
7515c08e1173703234cc2913757f237ee916087498aklu}
7525c08e1173703234cc2913757f237ee916087498aklu
7535c08e1173703234cc2913757f237ee916087498aklu/**
7545c08e1173703234cc2913757f237ee916087498aklu  Function compares a device path data structure to that of all the nodes of a
7555c08e1173703234cc2913757f237ee916087498aklu  second device path instance.
7565c08e1173703234cc2913757f237ee916087498aklu
7575c08e1173703234cc2913757f237ee916087498aklu  @param  Multi                 A pointer to a multi-instance device path data
7585c08e1173703234cc2913757f237ee916087498aklu                                structure.
7595c08e1173703234cc2913757f237ee916087498aklu  @param  Single                A pointer to a single-instance device path data
7605c08e1173703234cc2913757f237ee916087498aklu                                structure.
7615c08e1173703234cc2913757f237ee916087498aklu
7625c08e1173703234cc2913757f237ee916087498aklu  @retval TRUE                  If the Single device path is contained within Multi device path.
7635c08e1173703234cc2913757f237ee916087498aklu  @retval FALSE                 The Single device path is not match within Multi device path.
7645c08e1173703234cc2913757f237ee916087498aklu
7655c08e1173703234cc2913757f237ee916087498aklu**/
7665c08e1173703234cc2913757f237ee916087498akluBOOLEAN
7675c08e1173703234cc2913757f237ee916087498akluEFIAPI
7685c08e1173703234cc2913757f237ee916087498akluBdsLibMatchDevicePaths (
7695c08e1173703234cc2913757f237ee916087498aklu  IN  EFI_DEVICE_PATH_PROTOCOL  *Multi,
7705c08e1173703234cc2913757f237ee916087498aklu  IN  EFI_DEVICE_PATH_PROTOCOL  *Single
7715c08e1173703234cc2913757f237ee916087498aklu  )
7725c08e1173703234cc2913757f237ee916087498aklu{
7735c08e1173703234cc2913757f237ee916087498aklu  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
7745c08e1173703234cc2913757f237ee916087498aklu  EFI_DEVICE_PATH_PROTOCOL  *DevicePathInst;
7755c08e1173703234cc2913757f237ee916087498aklu  UINTN                     Size;
7765c08e1173703234cc2913757f237ee916087498aklu
7775c08e1173703234cc2913757f237ee916087498aklu  if (Multi == NULL || Single  == NULL) {
7785c08e1173703234cc2913757f237ee916087498aklu    return FALSE;
7795c08e1173703234cc2913757f237ee916087498aklu  }
7805c08e1173703234cc2913757f237ee916087498aklu
7815c08e1173703234cc2913757f237ee916087498aklu  DevicePath      = Multi;
7825c08e1173703234cc2913757f237ee916087498aklu  DevicePathInst  = GetNextDevicePathInstance (&DevicePath, &Size);
7835c08e1173703234cc2913757f237ee916087498aklu
7845c08e1173703234cc2913757f237ee916087498aklu  //
7855c08e1173703234cc2913757f237ee916087498aklu  // Search for the match of 'Single' in 'Multi'
7865c08e1173703234cc2913757f237ee916087498aklu  //
7875c08e1173703234cc2913757f237ee916087498aklu  while (DevicePathInst != NULL) {
7885c08e1173703234cc2913757f237ee916087498aklu    //
7895c08e1173703234cc2913757f237ee916087498aklu    // If the single device path is found in multiple device paths,
7905c08e1173703234cc2913757f237ee916087498aklu    // return success
7915c08e1173703234cc2913757f237ee916087498aklu    //
7925c08e1173703234cc2913757f237ee916087498aklu    if (CompareMem (Single, DevicePathInst, Size) == 0) {
7935c08e1173703234cc2913757f237ee916087498aklu      FreePool (DevicePathInst);
7945c08e1173703234cc2913757f237ee916087498aklu      return TRUE;
7955c08e1173703234cc2913757f237ee916087498aklu    }
7965c08e1173703234cc2913757f237ee916087498aklu
7975c08e1173703234cc2913757f237ee916087498aklu    FreePool (DevicePathInst);
7985c08e1173703234cc2913757f237ee916087498aklu    DevicePathInst = GetNextDevicePathInstance (&DevicePath, &Size);
7995c08e1173703234cc2913757f237ee916087498aklu  }
8005c08e1173703234cc2913757f237ee916087498aklu
8015c08e1173703234cc2913757f237ee916087498aklu  return FALSE;
8025c08e1173703234cc2913757f237ee916087498aklu}
8035c08e1173703234cc2913757f237ee916087498aklu
8045c08e1173703234cc2913757f237ee916087498aklu/**
8055c08e1173703234cc2913757f237ee916087498aklu  This function prints a series of strings.
8065c08e1173703234cc2913757f237ee916087498aklu
8075c08e1173703234cc2913757f237ee916087498aklu  @param  ConOut                Pointer to EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
8085c08e1173703234cc2913757f237ee916087498aklu  @param  ...                   A variable argument list containing series of
8095c08e1173703234cc2913757f237ee916087498aklu                                strings, the last string must be NULL.
8105c08e1173703234cc2913757f237ee916087498aklu
8115c08e1173703234cc2913757f237ee916087498aklu  @retval EFI_SUCCESS           Success print out the string using ConOut.
8125c08e1173703234cc2913757f237ee916087498aklu  @retval EFI_STATUS            Return the status of the ConOut->OutputString ().
8135c08e1173703234cc2913757f237ee916087498aklu
8145c08e1173703234cc2913757f237ee916087498aklu**/
8155c08e1173703234cc2913757f237ee916087498akluEFI_STATUS
8165c08e1173703234cc2913757f237ee916087498akluEFIAPI
8175c08e1173703234cc2913757f237ee916087498akluBdsLibOutputStrings (
8185c08e1173703234cc2913757f237ee916087498aklu  IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL   *ConOut,
8195c08e1173703234cc2913757f237ee916087498aklu  ...
8205c08e1173703234cc2913757f237ee916087498aklu  )
8215c08e1173703234cc2913757f237ee916087498aklu{
8225c08e1173703234cc2913757f237ee916087498aklu  VA_LIST     Args;
8235c08e1173703234cc2913757f237ee916087498aklu  EFI_STATUS  Status;
8245c08e1173703234cc2913757f237ee916087498aklu  CHAR16      *String;
8255c08e1173703234cc2913757f237ee916087498aklu
8265c08e1173703234cc2913757f237ee916087498aklu  Status = EFI_SUCCESS;
8275c08e1173703234cc2913757f237ee916087498aklu  VA_START (Args, ConOut);
8285c08e1173703234cc2913757f237ee916087498aklu
8295c08e1173703234cc2913757f237ee916087498aklu  while (!EFI_ERROR (Status)) {
8305c08e1173703234cc2913757f237ee916087498aklu    //
8315c08e1173703234cc2913757f237ee916087498aklu    // If String is NULL, then it's the end of the list
8325c08e1173703234cc2913757f237ee916087498aklu    //
8335c08e1173703234cc2913757f237ee916087498aklu    String = VA_ARG (Args, CHAR16 *);
8345c08e1173703234cc2913757f237ee916087498aklu    if (String != NULL) {
8355c08e1173703234cc2913757f237ee916087498aklu      break;
8365c08e1173703234cc2913757f237ee916087498aklu    }
8375c08e1173703234cc2913757f237ee916087498aklu
8385c08e1173703234cc2913757f237ee916087498aklu    Status = ConOut->OutputString (ConOut, String);
8395c08e1173703234cc2913757f237ee916087498aklu
8405c08e1173703234cc2913757f237ee916087498aklu    if (EFI_ERROR (Status)) {
8415c08e1173703234cc2913757f237ee916087498aklu      break;
8425c08e1173703234cc2913757f237ee916087498aklu    }
8435c08e1173703234cc2913757f237ee916087498aklu  }
8445c08e1173703234cc2913757f237ee916087498aklu
8455c08e1173703234cc2913757f237ee916087498aklu  VA_END(Args);
8465c08e1173703234cc2913757f237ee916087498aklu  return Status;
8475c08e1173703234cc2913757f237ee916087498aklu}
8485c08e1173703234cc2913757f237ee916087498aklu
8495c08e1173703234cc2913757f237ee916087498aklu//
8505c08e1173703234cc2913757f237ee916087498aklu//  Following are BDS Lib functions which  contain all the code about setup browser reset reminder feature.
8515c08e1173703234cc2913757f237ee916087498aklu//  Setup Browser reset reminder feature is that an reset reminder will be given before user leaves the setup browser  if
8525c08e1173703234cc2913757f237ee916087498aklu//  user change any option setting which needs a reset to be effective, and  the reset will be applied according to  the user selection.
8535c08e1173703234cc2913757f237ee916087498aklu//
8545c08e1173703234cc2913757f237ee916087498aklu
8555c08e1173703234cc2913757f237ee916087498aklu
8565c08e1173703234cc2913757f237ee916087498aklu/**
8575c08e1173703234cc2913757f237ee916087498aklu  Enable the setup browser reset reminder feature.
8585c08e1173703234cc2913757f237ee916087498aklu  This routine is used in platform tip. If the platform policy need the feature, use the routine to enable it.
8595c08e1173703234cc2913757f237ee916087498aklu
8605c08e1173703234cc2913757f237ee916087498aklu**/
8615c08e1173703234cc2913757f237ee916087498akluVOID
8625c08e1173703234cc2913757f237ee916087498akluEFIAPI
8635c08e1173703234cc2913757f237ee916087498akluEnableResetReminderFeature (
8645c08e1173703234cc2913757f237ee916087498aklu  VOID
8655c08e1173703234cc2913757f237ee916087498aklu  )
8665c08e1173703234cc2913757f237ee916087498aklu{
8675c08e1173703234cc2913757f237ee916087498aklu  mFeaturerSwitch = TRUE;
8685c08e1173703234cc2913757f237ee916087498aklu}
8695c08e1173703234cc2913757f237ee916087498aklu
8705c08e1173703234cc2913757f237ee916087498aklu
8715c08e1173703234cc2913757f237ee916087498aklu/**
8725c08e1173703234cc2913757f237ee916087498aklu  Disable the setup browser reset reminder feature.
8735c08e1173703234cc2913757f237ee916087498aklu  This routine is used in platform tip. If the platform policy do not want the feature, use the routine to disable it.
8745c08e1173703234cc2913757f237ee916087498aklu
8755c08e1173703234cc2913757f237ee916087498aklu**/
8765c08e1173703234cc2913757f237ee916087498akluVOID
8775c08e1173703234cc2913757f237ee916087498akluEFIAPI
8785c08e1173703234cc2913757f237ee916087498akluDisableResetReminderFeature (
8795c08e1173703234cc2913757f237ee916087498aklu  VOID
8805c08e1173703234cc2913757f237ee916087498aklu  )
8815c08e1173703234cc2913757f237ee916087498aklu{
8825c08e1173703234cc2913757f237ee916087498aklu  mFeaturerSwitch = FALSE;
8835c08e1173703234cc2913757f237ee916087498aklu}
8845c08e1173703234cc2913757f237ee916087498aklu
8855c08e1173703234cc2913757f237ee916087498aklu
8865c08e1173703234cc2913757f237ee916087498aklu/**
8875c08e1173703234cc2913757f237ee916087498aklu  Record the info that  a reset is required.
8885c08e1173703234cc2913757f237ee916087498aklu  A  module boolean variable is used to record whether a reset is required.
8895c08e1173703234cc2913757f237ee916087498aklu
8905c08e1173703234cc2913757f237ee916087498aklu**/
8915c08e1173703234cc2913757f237ee916087498akluVOID
8925c08e1173703234cc2913757f237ee916087498akluEFIAPI
8935c08e1173703234cc2913757f237ee916087498akluEnableResetRequired (
8945c08e1173703234cc2913757f237ee916087498aklu  VOID
8955c08e1173703234cc2913757f237ee916087498aklu  )
8965c08e1173703234cc2913757f237ee916087498aklu{
8975c08e1173703234cc2913757f237ee916087498aklu  mResetRequired = TRUE;
8985c08e1173703234cc2913757f237ee916087498aklu}
8995c08e1173703234cc2913757f237ee916087498aklu
9005c08e1173703234cc2913757f237ee916087498aklu
9015c08e1173703234cc2913757f237ee916087498aklu/**
9025c08e1173703234cc2913757f237ee916087498aklu  Record the info that  no reset is required.
9035c08e1173703234cc2913757f237ee916087498aklu  A  module boolean variable is used to record whether a reset is required.
9045c08e1173703234cc2913757f237ee916087498aklu
9055c08e1173703234cc2913757f237ee916087498aklu**/
9065c08e1173703234cc2913757f237ee916087498akluVOID
9075c08e1173703234cc2913757f237ee916087498akluEFIAPI
9085c08e1173703234cc2913757f237ee916087498akluDisableResetRequired (
9095c08e1173703234cc2913757f237ee916087498aklu  VOID
9105c08e1173703234cc2913757f237ee916087498aklu  )
9115c08e1173703234cc2913757f237ee916087498aklu{
9125c08e1173703234cc2913757f237ee916087498aklu  mResetRequired = FALSE;
9135c08e1173703234cc2913757f237ee916087498aklu}
9145c08e1173703234cc2913757f237ee916087498aklu
9155c08e1173703234cc2913757f237ee916087498aklu
9165c08e1173703234cc2913757f237ee916087498aklu/**
9175c08e1173703234cc2913757f237ee916087498aklu  Check whether platform policy enable the reset reminder feature. The default is enabled.
9185c08e1173703234cc2913757f237ee916087498aklu
9195c08e1173703234cc2913757f237ee916087498aklu**/
9205c08e1173703234cc2913757f237ee916087498akluBOOLEAN
9215c08e1173703234cc2913757f237ee916087498akluEFIAPI
9225c08e1173703234cc2913757f237ee916087498akluIsResetReminderFeatureEnable (
9235c08e1173703234cc2913757f237ee916087498aklu  VOID
9245c08e1173703234cc2913757f237ee916087498aklu  )
9255c08e1173703234cc2913757f237ee916087498aklu{
9265c08e1173703234cc2913757f237ee916087498aklu  return mFeaturerSwitch;
9275c08e1173703234cc2913757f237ee916087498aklu}
9285c08e1173703234cc2913757f237ee916087498aklu
9295c08e1173703234cc2913757f237ee916087498aklu
9305c08e1173703234cc2913757f237ee916087498aklu/**
9315c08e1173703234cc2913757f237ee916087498aklu  Check if  user changed any option setting which needs a system reset to be effective.
9325c08e1173703234cc2913757f237ee916087498aklu
9335c08e1173703234cc2913757f237ee916087498aklu**/
9345c08e1173703234cc2913757f237ee916087498akluBOOLEAN
9355c08e1173703234cc2913757f237ee916087498akluEFIAPI
9365c08e1173703234cc2913757f237ee916087498akluIsResetRequired (
9375c08e1173703234cc2913757f237ee916087498aklu  VOID
9385c08e1173703234cc2913757f237ee916087498aklu  )
9395c08e1173703234cc2913757f237ee916087498aklu{
9405c08e1173703234cc2913757f237ee916087498aklu  return mResetRequired;
9415c08e1173703234cc2913757f237ee916087498aklu}
9425c08e1173703234cc2913757f237ee916087498aklu
9435c08e1173703234cc2913757f237ee916087498aklu
9445c08e1173703234cc2913757f237ee916087498aklu/**
9455c08e1173703234cc2913757f237ee916087498aklu  Check whether a reset is needed, and finish the reset reminder feature.
9465c08e1173703234cc2913757f237ee916087498aklu  If a reset is needed, Popup a menu to notice user, and finish the feature
9475c08e1173703234cc2913757f237ee916087498aklu  according to the user selection.
9485c08e1173703234cc2913757f237ee916087498aklu
9495c08e1173703234cc2913757f237ee916087498aklu**/
9505c08e1173703234cc2913757f237ee916087498akluVOID
9515c08e1173703234cc2913757f237ee916087498akluEFIAPI
9525c08e1173703234cc2913757f237ee916087498akluSetupResetReminder (
9535c08e1173703234cc2913757f237ee916087498aklu  VOID
9545c08e1173703234cc2913757f237ee916087498aklu  )
9555c08e1173703234cc2913757f237ee916087498aklu{
9565c08e1173703234cc2913757f237ee916087498aklu  EFI_INPUT_KEY                 Key;
9575c08e1173703234cc2913757f237ee916087498aklu  CHAR16                        *StringBuffer1;
9585c08e1173703234cc2913757f237ee916087498aklu  CHAR16                        *StringBuffer2;
9595c08e1173703234cc2913757f237ee916087498aklu
9605c08e1173703234cc2913757f237ee916087498aklu
9615c08e1173703234cc2913757f237ee916087498aklu  //
9625c08e1173703234cc2913757f237ee916087498aklu  //check any reset required change is applied? if yes, reset system
9635c08e1173703234cc2913757f237ee916087498aklu  //
9645c08e1173703234cc2913757f237ee916087498aklu  if (IsResetReminderFeatureEnable ()) {
9655c08e1173703234cc2913757f237ee916087498aklu    if (IsResetRequired ()) {
9665c08e1173703234cc2913757f237ee916087498aklu
9675c08e1173703234cc2913757f237ee916087498aklu      StringBuffer1 = AllocateZeroPool (MAX_STRING_LEN * sizeof (CHAR16));
9685c08e1173703234cc2913757f237ee916087498aklu      ASSERT (StringBuffer1 != NULL);
9695c08e1173703234cc2913757f237ee916087498aklu      StringBuffer2 = AllocateZeroPool (MAX_STRING_LEN * sizeof (CHAR16));
9705c08e1173703234cc2913757f237ee916087498aklu      ASSERT (StringBuffer2 != NULL);
9715c08e1173703234cc2913757f237ee916087498aklu      StrCpy (StringBuffer1, L"Configuration changed. Reset to apply it Now ? ");
9725c08e1173703234cc2913757f237ee916087498aklu      StrCpy (StringBuffer2, L"Enter (YES)  /   Esc (NO)");
9735c08e1173703234cc2913757f237ee916087498aklu      //
9745c08e1173703234cc2913757f237ee916087498aklu      // Popup a menu to notice user
9755c08e1173703234cc2913757f237ee916087498aklu      //
9765c08e1173703234cc2913757f237ee916087498aklu      do {
9775c08e1173703234cc2913757f237ee916087498aklu        IfrLibCreatePopUp (2, &Key, StringBuffer1, StringBuffer2);
9785c08e1173703234cc2913757f237ee916087498aklu      } while ((Key.ScanCode != SCAN_ESC) && (Key.UnicodeChar != CHAR_CARRIAGE_RETURN));
9795c08e1173703234cc2913757f237ee916087498aklu
9805c08e1173703234cc2913757f237ee916087498aklu      FreePool (StringBuffer1);
9815c08e1173703234cc2913757f237ee916087498aklu      FreePool (StringBuffer2);
9825c08e1173703234cc2913757f237ee916087498aklu      //
9835c08e1173703234cc2913757f237ee916087498aklu      // If the user hits the YES Response key, reset
9845c08e1173703234cc2913757f237ee916087498aklu      //
9855c08e1173703234cc2913757f237ee916087498aklu      if ((Key.UnicodeChar == CHAR_CARRIAGE_RETURN)) {
9865c08e1173703234cc2913757f237ee916087498aklu        gRT->ResetSystem (EfiResetCold, EFI_SUCCESS, 0, NULL);
9875c08e1173703234cc2913757f237ee916087498aklu      }
9885c08e1173703234cc2913757f237ee916087498aklu      gST->ConOut->ClearScreen (gST->ConOut);
9895c08e1173703234cc2913757f237ee916087498aklu    }
9905c08e1173703234cc2913757f237ee916087498aklu  }
9915c08e1173703234cc2913757f237ee916087498aklu}
9925c08e1173703234cc2913757f237ee916087498aklu
9935c08e1173703234cc2913757f237ee916087498aklu/**
9945c08e1173703234cc2913757f237ee916087498aklu  Get the headers (dos, image, optional header) from an image
9955c08e1173703234cc2913757f237ee916087498aklu
9965c08e1173703234cc2913757f237ee916087498aklu  @param  Device                SimpleFileSystem device handle
9975c08e1173703234cc2913757f237ee916087498aklu  @param  FileName              File name for the image
9985c08e1173703234cc2913757f237ee916087498aklu  @param  DosHeader             Pointer to dos header
9995c08e1173703234cc2913757f237ee916087498aklu  @param  Hdr                   The buffer in which to return the PE32, PE32+, or TE header.
10005c08e1173703234cc2913757f237ee916087498aklu
10015c08e1173703234cc2913757f237ee916087498aklu  @retval EFI_SUCCESS           Successfully get the machine type.
10025c08e1173703234cc2913757f237ee916087498aklu  @retval EFI_NOT_FOUND         The file is not found.
10035c08e1173703234cc2913757f237ee916087498aklu  @retval EFI_LOAD_ERROR        File is not a valid image file.
10045c08e1173703234cc2913757f237ee916087498aklu
10055c08e1173703234cc2913757f237ee916087498aklu**/
10065c08e1173703234cc2913757f237ee916087498akluEFI_STATUS
10075c08e1173703234cc2913757f237ee916087498akluEFIAPI
10085c08e1173703234cc2913757f237ee916087498akluBdsLibGetImageHeader (
10095c08e1173703234cc2913757f237ee916087498aklu  IN  EFI_HANDLE                  Device,
10105c08e1173703234cc2913757f237ee916087498aklu  IN  CHAR16                      *FileName,
10115c08e1173703234cc2913757f237ee916087498aklu  OUT EFI_IMAGE_DOS_HEADER        *DosHeader,
10125c08e1173703234cc2913757f237ee916087498aklu  OUT EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION   Hdr
10135c08e1173703234cc2913757f237ee916087498aklu  )
10145c08e1173703234cc2913757f237ee916087498aklu{
10155c08e1173703234cc2913757f237ee916087498aklu  EFI_STATUS                       Status;
10165c08e1173703234cc2913757f237ee916087498aklu  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL  *Volume;
10175c08e1173703234cc2913757f237ee916087498aklu  EFI_FILE_HANDLE                  Root;
10185c08e1173703234cc2913757f237ee916087498aklu  EFI_FILE_HANDLE                  ThisFile;
10195c08e1173703234cc2913757f237ee916087498aklu  UINTN                            BufferSize;
10205c08e1173703234cc2913757f237ee916087498aklu  UINT64                           FileSize;
10215c08e1173703234cc2913757f237ee916087498aklu  EFI_FILE_INFO                    *Info;
10225c08e1173703234cc2913757f237ee916087498aklu
10235c08e1173703234cc2913757f237ee916087498aklu  Root     = NULL;
10245c08e1173703234cc2913757f237ee916087498aklu  ThisFile = NULL;
10255c08e1173703234cc2913757f237ee916087498aklu  //
10265c08e1173703234cc2913757f237ee916087498aklu  // Handle the file system interface to the device
10275c08e1173703234cc2913757f237ee916087498aklu  //
10285c08e1173703234cc2913757f237ee916087498aklu  Status = gBS->HandleProtocol (
10295c08e1173703234cc2913757f237ee916087498aklu                  Device,
10305c08e1173703234cc2913757f237ee916087498aklu                  &gEfiSimpleFileSystemProtocolGuid,
10315c08e1173703234cc2913757f237ee916087498aklu                  (VOID *) &Volume
10325c08e1173703234cc2913757f237ee916087498aklu                  );
10335c08e1173703234cc2913757f237ee916087498aklu  if (EFI_ERROR (Status)) {
10345c08e1173703234cc2913757f237ee916087498aklu    goto Done;
10355c08e1173703234cc2913757f237ee916087498aklu  }
10365c08e1173703234cc2913757f237ee916087498aklu
10375c08e1173703234cc2913757f237ee916087498aklu  Status = Volume->OpenVolume (
10385c08e1173703234cc2913757f237ee916087498aklu                     Volume,
10395c08e1173703234cc2913757f237ee916087498aklu                     &Root
10405c08e1173703234cc2913757f237ee916087498aklu                     );
10415c08e1173703234cc2913757f237ee916087498aklu  if (EFI_ERROR (Status)) {
10425c08e1173703234cc2913757f237ee916087498aklu    Root = NULL;
10435c08e1173703234cc2913757f237ee916087498aklu    goto Done;
10445c08e1173703234cc2913757f237ee916087498aklu  }
10455c08e1173703234cc2913757f237ee916087498aklu
10465c08e1173703234cc2913757f237ee916087498aklu  Status = Root->Open (Root, &ThisFile, FileName, EFI_FILE_MODE_READ, 0);
10475c08e1173703234cc2913757f237ee916087498aklu  if (EFI_ERROR (Status)) {
10485c08e1173703234cc2913757f237ee916087498aklu    goto Done;
10495c08e1173703234cc2913757f237ee916087498aklu  }
10505c08e1173703234cc2913757f237ee916087498aklu
10515c08e1173703234cc2913757f237ee916087498aklu  //
10525c08e1173703234cc2913757f237ee916087498aklu  // Get file size
10535c08e1173703234cc2913757f237ee916087498aklu  //
10545c08e1173703234cc2913757f237ee916087498aklu  BufferSize  = SIZE_OF_EFI_FILE_INFO + 200;
10555c08e1173703234cc2913757f237ee916087498aklu  do {
10565c08e1173703234cc2913757f237ee916087498aklu    Info   = NULL;
10575c08e1173703234cc2913757f237ee916087498aklu    Status = gBS->AllocatePool (EfiBootServicesData, BufferSize, (VOID **) &Info);
10585c08e1173703234cc2913757f237ee916087498aklu    if (EFI_ERROR (Status)) {
10595c08e1173703234cc2913757f237ee916087498aklu      goto Done;
10605c08e1173703234cc2913757f237ee916087498aklu    }
10615c08e1173703234cc2913757f237ee916087498aklu    Status = ThisFile->GetInfo (
10625c08e1173703234cc2913757f237ee916087498aklu                         ThisFile,
10635c08e1173703234cc2913757f237ee916087498aklu                         &gEfiFileInfoGuid,
10645c08e1173703234cc2913757f237ee916087498aklu                         &BufferSize,
10655c08e1173703234cc2913757f237ee916087498aklu                         Info
10665c08e1173703234cc2913757f237ee916087498aklu                         );
10675c08e1173703234cc2913757f237ee916087498aklu    if (!EFI_ERROR (Status)) {
10685c08e1173703234cc2913757f237ee916087498aklu      break;
10695c08e1173703234cc2913757f237ee916087498aklu    }
10705c08e1173703234cc2913757f237ee916087498aklu    if (Status != EFI_BUFFER_TOO_SMALL) {
10715c08e1173703234cc2913757f237ee916087498aklu      FreePool (Info);
10725c08e1173703234cc2913757f237ee916087498aklu      goto Done;
10735c08e1173703234cc2913757f237ee916087498aklu    }
10745c08e1173703234cc2913757f237ee916087498aklu    FreePool (Info);
10755c08e1173703234cc2913757f237ee916087498aklu  } while (TRUE);
10765c08e1173703234cc2913757f237ee916087498aklu
10775c08e1173703234cc2913757f237ee916087498aklu  FileSize = Info->FileSize;
10785c08e1173703234cc2913757f237ee916087498aklu  FreePool (Info);
10795c08e1173703234cc2913757f237ee916087498aklu
10805c08e1173703234cc2913757f237ee916087498aklu  //
10815c08e1173703234cc2913757f237ee916087498aklu  // Read dos header
10825c08e1173703234cc2913757f237ee916087498aklu  //
10835c08e1173703234cc2913757f237ee916087498aklu  BufferSize = sizeof (EFI_IMAGE_DOS_HEADER);
10845c08e1173703234cc2913757f237ee916087498aklu  Status = ThisFile->Read (ThisFile, &BufferSize, DosHeader);
10855c08e1173703234cc2913757f237ee916087498aklu  if (EFI_ERROR (Status) ||
10865c08e1173703234cc2913757f237ee916087498aklu      BufferSize < sizeof (EFI_IMAGE_DOS_HEADER) ||
10875c08e1173703234cc2913757f237ee916087498aklu      FileSize <= DosHeader->e_lfanew ||
10885c08e1173703234cc2913757f237ee916087498aklu      DosHeader->e_magic != EFI_IMAGE_DOS_SIGNATURE) {
10895c08e1173703234cc2913757f237ee916087498aklu    Status = EFI_LOAD_ERROR;
10905c08e1173703234cc2913757f237ee916087498aklu    goto Done;
10915c08e1173703234cc2913757f237ee916087498aklu  }
10925c08e1173703234cc2913757f237ee916087498aklu
10935c08e1173703234cc2913757f237ee916087498aklu  //
10945c08e1173703234cc2913757f237ee916087498aklu  // Move to PE signature
10955c08e1173703234cc2913757f237ee916087498aklu  //
10965c08e1173703234cc2913757f237ee916087498aklu  Status = ThisFile->SetPosition (ThisFile, DosHeader->e_lfanew);
10975c08e1173703234cc2913757f237ee916087498aklu  if (EFI_ERROR (Status)) {
10985c08e1173703234cc2913757f237ee916087498aklu    Status = EFI_LOAD_ERROR;
10995c08e1173703234cc2913757f237ee916087498aklu    goto Done;
11005c08e1173703234cc2913757f237ee916087498aklu  }
11015c08e1173703234cc2913757f237ee916087498aklu
11025c08e1173703234cc2913757f237ee916087498aklu  //
11035c08e1173703234cc2913757f237ee916087498aklu  // Read and check PE signature
11045c08e1173703234cc2913757f237ee916087498aklu  //
11055c08e1173703234cc2913757f237ee916087498aklu  BufferSize = sizeof (EFI_IMAGE_OPTIONAL_HEADER_UNION);
11065c08e1173703234cc2913757f237ee916087498aklu  Status = ThisFile->Read (ThisFile, &BufferSize, Hdr.Pe32);
11075c08e1173703234cc2913757f237ee916087498aklu  if (EFI_ERROR (Status) ||
11085c08e1173703234cc2913757f237ee916087498aklu      BufferSize < sizeof (EFI_IMAGE_OPTIONAL_HEADER_UNION) ||
11095c08e1173703234cc2913757f237ee916087498aklu      Hdr.Pe32->Signature != EFI_IMAGE_NT_SIGNATURE) {
11105c08e1173703234cc2913757f237ee916087498aklu    Status = EFI_LOAD_ERROR;
11115c08e1173703234cc2913757f237ee916087498aklu    goto Done;
11125c08e1173703234cc2913757f237ee916087498aklu  }
11135c08e1173703234cc2913757f237ee916087498aklu
11145c08e1173703234cc2913757f237ee916087498aklu  //
11155c08e1173703234cc2913757f237ee916087498aklu  // Check PE32 or PE32+ magic
11165c08e1173703234cc2913757f237ee916087498aklu  //
11175c08e1173703234cc2913757f237ee916087498aklu  if (Hdr.Pe32->OptionalHeader.Magic != EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC &&
11185c08e1173703234cc2913757f237ee916087498aklu      Hdr.Pe32->OptionalHeader.Magic != EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
11195c08e1173703234cc2913757f237ee916087498aklu    Status = EFI_LOAD_ERROR;
11205c08e1173703234cc2913757f237ee916087498aklu    goto Done;
11215c08e1173703234cc2913757f237ee916087498aklu  }
11225c08e1173703234cc2913757f237ee916087498aklu
11235c08e1173703234cc2913757f237ee916087498aklu Done:
11245c08e1173703234cc2913757f237ee916087498aklu  if (ThisFile != NULL) {
11255c08e1173703234cc2913757f237ee916087498aklu    ThisFile->Close (ThisFile);
11265c08e1173703234cc2913757f237ee916087498aklu  }
11275c08e1173703234cc2913757f237ee916087498aklu  if (Root != NULL) {
11285c08e1173703234cc2913757f237ee916087498aklu    Root->Close (Root);
11295c08e1173703234cc2913757f237ee916087498aklu  }
11305c08e1173703234cc2913757f237ee916087498aklu  return Status;
11315c08e1173703234cc2913757f237ee916087498aklu}
11325c08e1173703234cc2913757f237ee916087498aklu
11335c08e1173703234cc2913757f237ee916087498aklu/**
11345c08e1173703234cc2913757f237ee916087498aklu
11355c08e1173703234cc2913757f237ee916087498aklu  This routine is a notification function for legayc boot or exit boot
11365c08e1173703234cc2913757f237ee916087498aklu  service event. It will adjust the memory information for different
11375c08e1173703234cc2913757f237ee916087498aklu  memory type and save them into the variables for next boot.
11385c08e1173703234cc2913757f237ee916087498aklu
11395c08e1173703234cc2913757f237ee916087498aklu
11405c08e1173703234cc2913757f237ee916087498aklu  @param Event           The event that triggered this notification function.
11415c08e1173703234cc2913757f237ee916087498aklu  @param Context         Pointer to the notification functions context.
11425c08e1173703234cc2913757f237ee916087498aklu
11435c08e1173703234cc2913757f237ee916087498aklu**/
11445c08e1173703234cc2913757f237ee916087498akluVOID
11455c08e1173703234cc2913757f237ee916087498akluEFIAPI
11465c08e1173703234cc2913757f237ee916087498akluBdsSetMemoryTypeInformationVariable (
11475c08e1173703234cc2913757f237ee916087498aklu  EFI_EVENT  Event,
11485c08e1173703234cc2913757f237ee916087498aklu  VOID       *Context
11495c08e1173703234cc2913757f237ee916087498aklu  )
11505c08e1173703234cc2913757f237ee916087498aklu{
11515c08e1173703234cc2913757f237ee916087498aklu  EFI_STATUS                   Status;
11525c08e1173703234cc2913757f237ee916087498aklu  EFI_MEMORY_TYPE_INFORMATION  *PreviousMemoryTypeInformation;
11535c08e1173703234cc2913757f237ee916087498aklu  EFI_MEMORY_TYPE_INFORMATION  *CurrentMemoryTypeInformation;
11545c08e1173703234cc2913757f237ee916087498aklu  UINTN                        VariableSize;
11555c08e1173703234cc2913757f237ee916087498aklu  BOOLEAN                      UpdateRequired;
11565c08e1173703234cc2913757f237ee916087498aklu  UINTN                        Index;
11575c08e1173703234cc2913757f237ee916087498aklu  UINTN                        Index1;
11585c08e1173703234cc2913757f237ee916087498aklu  UINT32                       Previous;
11595c08e1173703234cc2913757f237ee916087498aklu  UINT32                       Current;
11605c08e1173703234cc2913757f237ee916087498aklu  UINT32                       Next;
11615c08e1173703234cc2913757f237ee916087498aklu  EFI_HOB_GUID_TYPE            *GuidHob;
11625c08e1173703234cc2913757f237ee916087498aklu
11635c08e1173703234cc2913757f237ee916087498aklu  UpdateRequired = FALSE;
11645c08e1173703234cc2913757f237ee916087498aklu
11655c08e1173703234cc2913757f237ee916087498aklu  //
11665c08e1173703234cc2913757f237ee916087498aklu  // Retrieve the current memory usage statistics.  If they are not found, then
11675c08e1173703234cc2913757f237ee916087498aklu  // no adjustments can be made to the Memory Type Information variable.
11685c08e1173703234cc2913757f237ee916087498aklu  //
11695c08e1173703234cc2913757f237ee916087498aklu  Status = EfiGetSystemConfigurationTable (
11705c08e1173703234cc2913757f237ee916087498aklu             &gEfiMemoryTypeInformationGuid,
11715c08e1173703234cc2913757f237ee916087498aklu             (VOID **) &CurrentMemoryTypeInformation
11725c08e1173703234cc2913757f237ee916087498aklu             );
11735c08e1173703234cc2913757f237ee916087498aklu  if (EFI_ERROR (Status) || CurrentMemoryTypeInformation == NULL) {
11745c08e1173703234cc2913757f237ee916087498aklu    return;
11755c08e1173703234cc2913757f237ee916087498aklu  }
11765c08e1173703234cc2913757f237ee916087498aklu
11775c08e1173703234cc2913757f237ee916087498aklu  //
11785c08e1173703234cc2913757f237ee916087498aklu  // Get the Memory Type Information settings from Hob if they exist,
11795c08e1173703234cc2913757f237ee916087498aklu  // PEI is responsible for getting them from variable and build a Hob to save them.
11805c08e1173703234cc2913757f237ee916087498aklu  // If the previous Memory Type Information is not available, then set defaults
11815c08e1173703234cc2913757f237ee916087498aklu  //
11825c08e1173703234cc2913757f237ee916087498aklu  GuidHob = GetFirstGuidHob (&gEfiMemoryTypeInformationGuid);
11835c08e1173703234cc2913757f237ee916087498aklu  if (GuidHob == NULL) {
11845c08e1173703234cc2913757f237ee916087498aklu    //
11855c08e1173703234cc2913757f237ee916087498aklu    // If Platform has not built Memory Type Info into the Hob, just return.
11865c08e1173703234cc2913757f237ee916087498aklu    //
11875c08e1173703234cc2913757f237ee916087498aklu    return;
11885c08e1173703234cc2913757f237ee916087498aklu  }
11895c08e1173703234cc2913757f237ee916087498aklu  PreviousMemoryTypeInformation = GET_GUID_HOB_DATA (GuidHob);
11905c08e1173703234cc2913757f237ee916087498aklu  VariableSize = GET_GUID_HOB_DATA_SIZE (GuidHob);
11915c08e1173703234cc2913757f237ee916087498aklu
11925c08e1173703234cc2913757f237ee916087498aklu  //
11935c08e1173703234cc2913757f237ee916087498aklu  // Use a heuristic to adjust the Memory Type Information for the next boot
11945c08e1173703234cc2913757f237ee916087498aklu  //
11955c08e1173703234cc2913757f237ee916087498aklu  for (Index = 0; PreviousMemoryTypeInformation[Index].Type != EfiMaxMemoryType; Index++) {
11965c08e1173703234cc2913757f237ee916087498aklu
11975c08e1173703234cc2913757f237ee916087498aklu    Current = 0;
11985c08e1173703234cc2913757f237ee916087498aklu    for (Index1 = 0; CurrentMemoryTypeInformation[Index1].Type != EfiMaxMemoryType; Index1++) {
11995c08e1173703234cc2913757f237ee916087498aklu      if (PreviousMemoryTypeInformation[Index].Type == CurrentMemoryTypeInformation[Index1].Type) {
12005c08e1173703234cc2913757f237ee916087498aklu        Current = CurrentMemoryTypeInformation[Index1].NumberOfPages;
12015c08e1173703234cc2913757f237ee916087498aklu        break;
12025c08e1173703234cc2913757f237ee916087498aklu      }
12035c08e1173703234cc2913757f237ee916087498aklu    }
12045c08e1173703234cc2913757f237ee916087498aklu
12055c08e1173703234cc2913757f237ee916087498aklu    if (CurrentMemoryTypeInformation[Index1].Type == EfiMaxMemoryType) {
12065c08e1173703234cc2913757f237ee916087498aklu      continue;
12075c08e1173703234cc2913757f237ee916087498aklu    }
12085c08e1173703234cc2913757f237ee916087498aklu
12095c08e1173703234cc2913757f237ee916087498aklu    Previous = PreviousMemoryTypeInformation[Index].NumberOfPages;
12105c08e1173703234cc2913757f237ee916087498aklu
12115c08e1173703234cc2913757f237ee916087498aklu    //
12125c08e1173703234cc2913757f237ee916087498aklu    // Write next varible to 125% * current and Inconsistent Memory Reserved across bootings may lead to S4 fail
12135c08e1173703234cc2913757f237ee916087498aklu    //
12145c08e1173703234cc2913757f237ee916087498aklu    if (Current > Previous) {
12155c08e1173703234cc2913757f237ee916087498aklu      Next = Current + (Current >> 2);
12165c08e1173703234cc2913757f237ee916087498aklu    } else {
12175c08e1173703234cc2913757f237ee916087498aklu      Next = Previous;
12185c08e1173703234cc2913757f237ee916087498aklu    }
12195c08e1173703234cc2913757f237ee916087498aklu    if (Next > 0 && Next < 4) {
12205c08e1173703234cc2913757f237ee916087498aklu      Next = 4;
12215c08e1173703234cc2913757f237ee916087498aklu    }
12225c08e1173703234cc2913757f237ee916087498aklu
12235c08e1173703234cc2913757f237ee916087498aklu    if (Next != Previous) {
12245c08e1173703234cc2913757f237ee916087498aklu      PreviousMemoryTypeInformation[Index].NumberOfPages = Next;
12255c08e1173703234cc2913757f237ee916087498aklu      UpdateRequired = TRUE;
12265c08e1173703234cc2913757f237ee916087498aklu    }
12275c08e1173703234cc2913757f237ee916087498aklu
12285c08e1173703234cc2913757f237ee916087498aklu  }
12295c08e1173703234cc2913757f237ee916087498aklu
12305c08e1173703234cc2913757f237ee916087498aklu  //
12315c08e1173703234cc2913757f237ee916087498aklu  // If any changes were made to the Memory Type Information settings, then set the new variable value
12325c08e1173703234cc2913757f237ee916087498aklu  //
12335c08e1173703234cc2913757f237ee916087498aklu  if (UpdateRequired) {
12345c08e1173703234cc2913757f237ee916087498aklu    Status = gRT->SetVariable (
12355c08e1173703234cc2913757f237ee916087498aklu          EFI_MEMORY_TYPE_INFORMATION_VARIABLE_NAME,
12365c08e1173703234cc2913757f237ee916087498aklu          &gEfiMemoryTypeInformationGuid,
12375c08e1173703234cc2913757f237ee916087498aklu          EFI_VARIABLE_NON_VOLATILE  | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
12385c08e1173703234cc2913757f237ee916087498aklu          VariableSize,
12395c08e1173703234cc2913757f237ee916087498aklu          PreviousMemoryTypeInformation
12405c08e1173703234cc2913757f237ee916087498aklu          );
12415c08e1173703234cc2913757f237ee916087498aklu  }
12425c08e1173703234cc2913757f237ee916087498aklu
12435c08e1173703234cc2913757f237ee916087498aklu  return;
12445c08e1173703234cc2913757f237ee916087498aklu}
12455c08e1173703234cc2913757f237ee916087498aklu
12465c08e1173703234cc2913757f237ee916087498aklu/**
12475c08e1173703234cc2913757f237ee916087498aklu  This routine register a function to adjust the different type memory page number
12485c08e1173703234cc2913757f237ee916087498aklu  just before booting and save the updated info into the variable for next boot to use.
12495c08e1173703234cc2913757f237ee916087498aklu
12505c08e1173703234cc2913757f237ee916087498aklu**/
12515c08e1173703234cc2913757f237ee916087498akluVOID
12525c08e1173703234cc2913757f237ee916087498akluEFIAPI
12535c08e1173703234cc2913757f237ee916087498akluBdsLibSaveMemoryTypeInformation (
12545c08e1173703234cc2913757f237ee916087498aklu  VOID
12555c08e1173703234cc2913757f237ee916087498aklu  )
12565c08e1173703234cc2913757f237ee916087498aklu{
12575c08e1173703234cc2913757f237ee916087498aklu  EFI_STATUS                   Status;
12585c08e1173703234cc2913757f237ee916087498aklu  EFI_EVENT                    ReadyToBootEvent;
12595c08e1173703234cc2913757f237ee916087498aklu
12605c08e1173703234cc2913757f237ee916087498aklu  Status = EfiCreateEventReadyToBootEx (
12615c08e1173703234cc2913757f237ee916087498aklu           TPL_CALLBACK,
12625c08e1173703234cc2913757f237ee916087498aklu           BdsSetMemoryTypeInformationVariable,
12635c08e1173703234cc2913757f237ee916087498aklu           NULL,
12645c08e1173703234cc2913757f237ee916087498aklu           &ReadyToBootEvent
12655c08e1173703234cc2913757f237ee916087498aklu           );
12665c08e1173703234cc2913757f237ee916087498aklu  if (EFI_ERROR (Status)) {
12675c08e1173703234cc2913757f237ee916087498aklu    DEBUG ((DEBUG_ERROR,"Bds Set Memory Type Informationa Variable Fails\n"));
12685c08e1173703234cc2913757f237ee916087498aklu  }
12695c08e1173703234cc2913757f237ee916087498aklu
12705c08e1173703234cc2913757f237ee916087498aklu}
12715c08e1173703234cc2913757f237ee916087498aklu
12725c08e1173703234cc2913757f237ee916087498aklu
1273