]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Library/UefiBootManagerLib/BmLoadOption.c
MdeModulePkg/Bds: Refine the code to load file from FV.
[mirror_edk2.git] / MdeModulePkg / Library / UefiBootManagerLib / BmLoadOption.c
index 07e62496291418e5d732714cea3092f4620ef291..696e995bb64e3516e45b31e8b554ba203be3eb7d 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
   Load option library functions which relate with creating and processing load options.\r
 \r
-Copyright (c) 2011 - 2015, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2011 - 2016, Intel Corporation. All rights reserved.<BR>\r
 (C) Copyright 2015 Hewlett Packard Enterprise Development LP<BR>\r
 This program and the accompanying materials\r
 are licensed and made available under the terms and conditions of the BSD License\r
@@ -19,14 +19,16 @@ GLOBAL_REMOVE_IF_UNREFERENCED
   CHAR16 *mBmLoadOptionName[] = {\r
     L"Driver",\r
     L"SysPrep",\r
-    L"Boot"\r
+    L"Boot",\r
+    L"PlatformRecovery"\r
   };\r
 \r
 GLOBAL_REMOVE_IF_UNREFERENCED\r
   CHAR16 *mBmLoadOptionOrderName[] = {\r
     EFI_DRIVER_ORDER_VARIABLE_NAME,\r
     EFI_SYS_PREP_ORDER_VARIABLE_NAME,\r
-    EFI_BOOT_ORDER_VARIABLE_NAME\r
+    EFI_BOOT_ORDER_VARIABLE_NAME,\r
+    NULL  // PlatformRecovery#### doesn't have associated *Order variable\r
   };\r
 \r
 /**\r
@@ -154,8 +156,9 @@ BmGetFreeOptionNumber (
 }\r
 \r
 /**\r
-  Create the Boot####, Driver####, SysPrep####, variable from the load option.\r
-  \r
+  Create the Boot####, Driver####, SysPrep####, PlatformRecovery#### variable\r
+  from the load option.\r
+\r
   @param  LoadOption      Pointer to the load option.\r
 \r
   @retval EFI_SUCCESS     The variable was created.\r
@@ -167,12 +170,14 @@ EfiBootManagerLoadOptionToVariable (
   IN CONST EFI_BOOT_MANAGER_LOAD_OPTION     *Option\r
   )\r
 {\r
+  EFI_STATUS                       Status;\r
   UINTN                            VariableSize;\r
   UINT8                            *Variable;\r
   UINT8                            *Ptr;\r
   CHAR16                           OptionName[BM_OPTION_NAME_LEN];\r
   CHAR16                           *Description;\r
   CHAR16                           NullChar;\r
+  EDKII_VARIABLE_LOCK_PROTOCOL     *VariableLock;\r
   UINT32                           VariableAttributes;\r
 \r
   if ((Option->OptionNumber == LoadOptionNumberUnassigned) ||\r
@@ -233,6 +238,17 @@ structure.
   UnicodeSPrint (OptionName, sizeof (OptionName), L"%s%04x", mBmLoadOptionName[Option->OptionType], Option->OptionNumber);\r
 \r
   VariableAttributes = EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE;\r
+  if (Option->OptionType == LoadOptionTypePlatformRecovery) {\r
+    //\r
+    // Lock the PlatformRecovery####\r
+    //\r
+    Status = gBS->LocateProtocol (&gEdkiiVariableLockProtocolGuid, NULL, (VOID **) &VariableLock);\r
+    if (!EFI_ERROR (Status)) {\r
+      Status = VariableLock->RequestToLock (VariableLock, OptionName, &gEfiGlobalVariableGuid);\r
+      ASSERT_EFI_ERROR (Status);\r
+    }\r
+    VariableAttributes = EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS;\r
+  }\r
 \r
   return gRT->SetVariable (\r
                 OptionName,\r
@@ -548,18 +564,17 @@ EfiBootManagerDeleteLoadOptionVariable (
 {\r
   UINT16                            *OptionOrder;\r
   UINTN                             OptionOrderSize;\r
-  EFI_STATUS                        Status;\r
   UINTN                             Index;\r
+  CHAR16                            OptionName[BM_OPTION_NAME_LEN];\r
 \r
   if (((UINT32) OptionType >= LoadOptionTypeMax) || (OptionNumber >= LoadOptionNumberMax)) {\r
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
-  Status = EFI_NOT_FOUND;\r
-\r
   if (OptionType == LoadOptionTypeDriver || OptionType == LoadOptionTypeSysPrep || OptionType == LoadOptionTypeBoot) {\r
     //\r
-    // If the associated *Order exists, just remove the reference in *Order.\r
+    // If the associated *Order exists, firstly remove the reference in *Order for\r
+    //  Driver####, SysPrep#### and Boot####.\r
     //\r
     GetEfiGlobalVariable2 (mBmLoadOptionOrderName[OptionType], (VOID **) &OptionOrder, &OptionOrderSize);\r
     ASSERT ((OptionOrder != NULL && OptionOrderSize != 0) || (OptionOrder == NULL && OptionOrderSize == 0));\r
@@ -568,13 +583,13 @@ EfiBootManagerDeleteLoadOptionVariable (
       if (OptionOrder[Index] == OptionNumber) {\r
         OptionOrderSize -= sizeof (UINT16);\r
         CopyMem (&OptionOrder[Index], &OptionOrder[Index + 1], OptionOrderSize - Index * sizeof (UINT16));\r
-        Status = gRT->SetVariable (\r
-          mBmLoadOptionOrderName[OptionType],\r
-          &gEfiGlobalVariableGuid,\r
-          EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
-          OptionOrderSize,\r
-          OptionOrder\r
-          );\r
+        gRT->SetVariable (\r
+               mBmLoadOptionOrderName[OptionType],\r
+               &gEfiGlobalVariableGuid,\r
+               EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
+               OptionOrderSize,\r
+               OptionOrder\r
+               );\r
         break;\r
       }\r
     }\r
@@ -583,30 +598,17 @@ EfiBootManagerDeleteLoadOptionVariable (
     }\r
   }\r
 \r
-  return Status;\r
-}\r
-\r
-/**\r
-  Convert a single character to number.\r
-  It assumes the input Char is in the scope of L'0' ~ L'9' and L'A' ~ L'F'\r
-\r
-  @param    Char   The input char which need to convert to int.\r
-**/\r
-UINTN\r
-BmCharToUint (\r
-  IN CHAR16                           Char\r
-  )\r
-{\r
-  if ((Char >= L'0') && (Char <= L'9')) {\r
-    return (UINTN) (Char - L'0');\r
-  }\r
-\r
-  if ((Char >= L'A') && (Char <= L'F')) {\r
-    return (UINTN) (Char - L'A' + 0xA);\r
-  }\r
-\r
-  ASSERT (FALSE);\r
-  return (UINTN) -1;\r
+  //\r
+  // Remove the Driver####, SysPrep####, Boot#### or PlatformRecovery#### itself.\r
+  //\r
+  UnicodeSPrint (OptionName, sizeof (OptionName), L"%s%04x", mBmLoadOptionName[OptionType], OptionNumber);\r
+  return gRT->SetVariable (\r
+                OptionName,\r
+                &gEfiGlobalVariableGuid,\r
+                0,\r
+                0,\r
+                NULL\r
+                );\r
 }\r
 \r
 /**\r
@@ -700,7 +702,8 @@ BmStrSizeEx (
 }\r
 \r
 /**\r
-  Validate the Boot####, Driver####, SysPrep#### variable (VendorGuid/Name)\r
+  Validate the Boot####, Driver####, SysPrep#### and PlatformRecovery####\r
+  variable (VendorGuid/Name)\r
 \r
   @param  Variable              The variable data.\r
   @param  VariableSize          The variable size.\r
@@ -943,6 +946,62 @@ EfiBootManagerVariableToLoadOption (
   return EfiBootManagerVariableToLoadOptionEx (VariableName, &gEfiGlobalVariableGuid, Option);\r
 }\r
 \r
+typedef struct {\r
+  EFI_BOOT_MANAGER_LOAD_OPTION_TYPE OptionType;\r
+  EFI_GUID                          *Guid;\r
+  EFI_BOOT_MANAGER_LOAD_OPTION      *Options;\r
+  UINTN                             OptionCount;\r
+} BM_COLLECT_LOAD_OPTIONS_PARAM;\r
+\r
+/**\r
+  Visitor function to collect the Platform Recovery load options or OS Recovery\r
+  load options from NV storage.\r
+\r
+  @param Name    Variable name.\r
+  @param Guid    Variable GUID.\r
+  @param Context The same context passed to BmForEachVariable.\r
+**/\r
+VOID\r
+BmCollectLoadOptions (\r
+  IN CHAR16               *Name,\r
+  IN EFI_GUID             *Guid,\r
+  IN VOID                 *Context\r
+  )\r
+{\r
+  EFI_STATUS                        Status;\r
+  EFI_BOOT_MANAGER_LOAD_OPTION_TYPE OptionType;\r
+  UINT16                            OptionNumber;\r
+  EFI_BOOT_MANAGER_LOAD_OPTION      Option;\r
+  UINTN                             Index;\r
+  BM_COLLECT_LOAD_OPTIONS_PARAM     *Param;\r
+\r
+  Param = (BM_COLLECT_LOAD_OPTIONS_PARAM *) Context;\r
+\r
+  if (CompareGuid (Guid, Param->Guid) && (\r
+      Param->OptionType == LoadOptionTypePlatformRecovery &&\r
+      BmIsValidLoadOptionVariableName (Name, &OptionType, &OptionNumber) &&\r
+      OptionType == LoadOptionTypePlatformRecovery\r
+     )) {\r
+    Status = EfiBootManagerVariableToLoadOptionEx (Name, Guid, &Option);\r
+    if (!EFI_ERROR (Status)) {\r
+      for (Index = 0; Index < Param->OptionCount; Index++) {\r
+        if (Param->Options[Index].OptionNumber > Option.OptionNumber) {\r
+          break;\r
+        }\r
+      }\r
+      Param->Options = ReallocatePool (\r
+                         Param->OptionCount * sizeof (EFI_BOOT_MANAGER_LOAD_OPTION),\r
+                         (Param->OptionCount + 1) * sizeof (EFI_BOOT_MANAGER_LOAD_OPTION),\r
+                         Param->Options\r
+                         );\r
+      ASSERT (Param->Options != NULL);\r
+      CopyMem (&Param->Options[Index + 1], &Param->Options[Index], (Param->OptionCount - Index) * sizeof (EFI_BOOT_MANAGER_LOAD_OPTION));\r
+      CopyMem (&Param->Options[Index], &Option, sizeof (EFI_BOOT_MANAGER_LOAD_OPTION));\r
+      Param->OptionCount++;\r
+    }\r
+  }\r
+}\r
+\r
 /**\r
   Returns an array of load options based on the EFI variable\r
   L"BootOrder"/L"DriverOrder" and the L"Boot####"/L"Driver####" variables impled by it.\r
@@ -962,16 +1021,18 @@ EfiBootManagerGetLoadOptions (
   IN EFI_BOOT_MANAGER_LOAD_OPTION_TYPE  LoadOptionType\r
   )\r
 {\r
-  EFI_STATUS                   Status;\r
-  UINT16                       *OptionOrder;\r
-  UINTN                        OptionOrderSize;\r
-  UINTN                        Index;\r
-  UINTN                        OptionIndex;\r
-  EFI_BOOT_MANAGER_LOAD_OPTION *Options;\r
-  CHAR16                       OptionName[BM_OPTION_NAME_LEN];\r
-  UINT16                       OptionNumber;\r
+  EFI_STATUS                    Status;\r
+  UINT16                        *OptionOrder;\r
+  UINTN                         OptionOrderSize;\r
+  UINTN                         Index;\r
+  UINTN                         OptionIndex;\r
+  EFI_BOOT_MANAGER_LOAD_OPTION  *Options;\r
+  CHAR16                        OptionName[BM_OPTION_NAME_LEN];\r
+  UINT16                        OptionNumber;\r
+  BM_COLLECT_LOAD_OPTIONS_PARAM Param;\r
 \r
   *OptionCount = 0;\r
+  Options      = NULL;\r
 \r
   if (LoadOptionType == LoadOptionTypeDriver || LoadOptionType == LoadOptionTypeSysPrep || LoadOptionType == LoadOptionTypeBoot) {\r
     //\r
@@ -1012,8 +1073,16 @@ EfiBootManagerGetLoadOptions (
       *OptionCount = OptionIndex;\r
     }\r
 \r
-  } else {\r
-    return NULL;\r
+  } else if (LoadOptionType == LoadOptionTypePlatformRecovery) {\r
+    Param.OptionType = LoadOptionTypePlatformRecovery;\r
+    Param.Options = NULL;\r
+    Param.OptionCount = 0;\r
+    Param.Guid = &gEfiGlobalVariableGuid;\r
+\r
+    BmForEachVariable (BmCollectLoadOptions, (VOID *) &Param);\r
+\r
+    *OptionCount = Param.OptionCount;\r
+    Options = Param.Options;\r
   }\r
 \r
   return Options;\r
@@ -1141,7 +1210,8 @@ BmIsLoadOptionPeHeaderValid (
         if ((Type == LoadOptionTypeDriver && Subsystem == EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER) ||\r
             (Type == LoadOptionTypeDriver && Subsystem == EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER) ||\r
             (Type == LoadOptionTypeSysPrep && Subsystem == EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION) ||\r
-            (Type == LoadOptionTypeBoot && Subsystem == EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION)\r
+            (Type == LoadOptionTypeBoot && Subsystem == EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION) ||\r
+            (Type == LoadOptionTypePlatformRecovery && Subsystem == EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION)\r
             ) {\r
           return TRUE;\r
         }\r