Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Ruiyu Ni <[email protected]>
Cc: Eric Dong <[email protected]>
---
 MdeModulePkg/Include/Library/UefiBootManagerLib.h  |   1 +
 .../Library/UefiBootManagerLib/BmLoadOption.c      | 130 ++++++++++++++++++---
 .../Library/UefiBootManagerLib/InternalBm.h        |   3 +-
 .../UefiBootManagerLib/UefiBootManagerLib.inf      |   1 +
 4 files changed, 118 insertions(+), 17 deletions(-)

diff --git a/MdeModulePkg/Include/Library/UefiBootManagerLib.h 
b/MdeModulePkg/Include/Library/UefiBootManagerLib.h
index 5538d90..1b04a8c 100644
--- a/MdeModulePkg/Include/Library/UefiBootManagerLib.h
+++ b/MdeModulePkg/Include/Library/UefiBootManagerLib.h
@@ -30,6 +30,7 @@ typedef enum {
   LoadOptionTypeDriver,
   LoadOptionTypeSysPrep,
   LoadOptionTypeBoot,
+  LoadOptionTypePlatformRecovery,
   LoadOptionTypeMax
 } EFI_BOOT_MANAGER_LOAD_OPTION_TYPE;
 
diff --git a/MdeModulePkg/Library/UefiBootManagerLib/BmLoadOption.c 
b/MdeModulePkg/Library/UefiBootManagerLib/BmLoadOption.c
index fbd7830..454fe20 100644
--- a/MdeModulePkg/Library/UefiBootManagerLib/BmLoadOption.c
+++ b/MdeModulePkg/Library/UefiBootManagerLib/BmLoadOption.c
@@ -18,14 +18,16 @@ GLOBAL_REMOVE_IF_UNREFERENCED
   CHAR16 *mBmLoadOptionName[] = {
     L"Driver",
     L"SysPrep",
-    L"Boot"
+    L"Boot",
+    L"PlatformRecovery"
   };
 
 GLOBAL_REMOVE_IF_UNREFERENCED
   CHAR16 *mBmLoadOptionOrderName[] = {
     EFI_DRIVER_ORDER_VARIABLE_NAME,
     EFI_SYS_PREP_ORDER_VARIABLE_NAME,
-    EFI_BOOT_ORDER_VARIABLE_NAME
+    EFI_BOOT_ORDER_VARIABLE_NAME,
+    NULL  // PlatformRecovery#### doesn't have associated *Order variable
   };
 
 /**
@@ -153,8 +155,9 @@ BmGetFreeOptionNumber (
 }
 
 /**
-  Create the Boot####, Driver####, SysPrep####, variable from the load option.
-  
+  Create the Boot####, Driver####, SysPrep####, PlatformRecovery#### variable
+  from the load option.
+
   @param  LoadOption      Pointer to the load option.
 
   @retval EFI_SUCCESS     The variable was created.
@@ -166,12 +169,14 @@ EfiBootManagerLoadOptionToVariable (
   IN CONST EFI_BOOT_MANAGER_LOAD_OPTION     *Option
   )
 {
+  EFI_STATUS                       Status;
   UINTN                            VariableSize;
   UINT8                            *Variable;
   UINT8                            *Ptr;
   CHAR16                           OptionName[BM_OPTION_NAME_LEN];
   CHAR16                           *Description;
   CHAR16                           NullChar;
+  EDKII_VARIABLE_LOCK_PROTOCOL     *VariableLock;
   UINT32                           VariableAttributes;
 
   if ((Option->OptionNumber == LoadOptionNumberUnassigned) ||
@@ -232,6 +237,17 @@ structure.
   UnicodeSPrint (OptionName, sizeof (OptionName), L"%s%04x", 
mBmLoadOptionName[Option->OptionType], Option->OptionNumber);
 
   VariableAttributes = EFI_VARIABLE_BOOTSERVICE_ACCESS | 
EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE;
+  if (Option->OptionType == LoadOptionTypePlatformRecovery) {
+    //
+    // Lock the PlatformRecovery####
+    //
+    Status = gBS->LocateProtocol (&gEdkiiVariableLockProtocolGuid, NULL, (VOID 
**) &VariableLock);
+    if (!EFI_ERROR (Status)) {
+      Status = VariableLock->RequestToLock (VariableLock, OptionName, 
&gEfiGlobalVariableGuid);
+      ASSERT_EFI_ERROR (Status);
+    }
+    VariableAttributes = EFI_VARIABLE_BOOTSERVICE_ACCESS | 
EFI_VARIABLE_RUNTIME_ACCESS;
+  }
 
   return gRT->SetVariable (
                 OptionName,
@@ -548,6 +564,7 @@ EfiBootManagerDeleteLoadOptionVariable (
   UINTN                             OptionOrderSize;
   EFI_STATUS                        Status;
   UINTN                             Index;
+  CHAR16                            OptionName[BM_OPTION_NAME_LEN];
 
   if (((UINT32) OptionType >= LoadOptionTypeMax) || (OptionNumber >= 
LoadOptionNumberMax)) {
     return EFI_INVALID_PARAMETER;
@@ -579,6 +596,19 @@ EfiBootManagerDeleteLoadOptionVariable (
     if (OptionOrder != NULL) {
       FreePool (OptionOrder);
     }
+  } else {
+    ASSERT (OptionType == LoadOptionTypePlatformRecovery);
+    //
+    // PlatformRecovery#### doesn't have assiciated PlatformRecoveryOrder, 
remove the PlatformRecovery#### itself.
+    //
+    UnicodeSPrint (OptionName, sizeof (OptionName), L"%s%04x", 
mBmLoadOptionName[OptionType], OptionNumber);
+    Status = gRT->SetVariable (
+                    OptionName,
+                    &gEfiGlobalVariableGuid,
+                    0,
+                    0,
+                    NULL
+                    );
   }
 
   return Status;
@@ -675,7 +705,8 @@ BmStrSizeEx (
 }
 
 /**
-  Validate the Boot####, Driver####, SysPrep#### variable (VendorGuid/Name)
+  Validate the Boot####, Driver####, SysPrep#### and PlatformRecovery####
+  variable (VendorGuid/Name)
 
   @param  Variable              The variable data.
   @param  VariableSize          The variable size.
@@ -918,6 +949,62 @@ EfiBootManagerVariableToLoadOption (
   return EfiBootManagerVariableToLoadOptionEx (VariableName, 
&gEfiGlobalVariableGuid, Option);
 }
 
+typedef struct {
+  EFI_BOOT_MANAGER_LOAD_OPTION_TYPE OptionType;
+  EFI_GUID                          *Guid;
+  EFI_BOOT_MANAGER_LOAD_OPTION      *Options;
+  UINTN                             OptionCount;
+} BM_COLLECT_LOAD_OPTIONS_PARAM;
+
+/**
+  Visitor function to collect the Platform Recovery load options or OS Recovery
+  load options from NV storage.
+
+  @param Name    Variable name.
+  @param Guid    Variable GUID.
+  @param Context The same context passed to BmForEachVariable.
+**/
+VOID
+BmCollectLoadOptions (
+  IN CHAR16               *Name,
+  IN EFI_GUID             *Guid,
+  IN VOID                 *Context
+  )
+{
+  EFI_STATUS                        Status;
+  EFI_BOOT_MANAGER_LOAD_OPTION_TYPE OptionType;
+  UINT16                            OptionNumber;
+  EFI_BOOT_MANAGER_LOAD_OPTION      Option;
+  UINTN                             Index;
+  BM_COLLECT_LOAD_OPTIONS_PARAM     *Param;
+
+  Param = (BM_COLLECT_LOAD_OPTIONS_PARAM *) Context;
+
+  if (CompareGuid (Guid, Param->Guid) && (
+      Param->OptionType == LoadOptionTypePlatformRecovery &&
+      BmIsValidLoadOptionVariableName (Name, &OptionType, &OptionNumber) &&
+      OptionType == LoadOptionTypePlatformRecovery
+     )) {
+    Status = EfiBootManagerVariableToLoadOptionEx (Name, Guid, &Option);
+    if (!EFI_ERROR (Status)) {
+      for (Index = 0; Index < Param->OptionCount; Index++) {
+        if (Param->Options[Index].OptionNumber > Option.OptionNumber) {
+          break;
+        }
+      }
+      Param->Options = ReallocatePool (
+                         Param->OptionCount * sizeof 
(EFI_BOOT_MANAGER_LOAD_OPTION),
+                         (Param->OptionCount + 1) * sizeof 
(EFI_BOOT_MANAGER_LOAD_OPTION),
+                         Param->Options
+                         );
+      ASSERT (Param->Options != NULL);
+      CopyMem (&Param->Options[Index + 1], &Param->Options[Index], 
(Param->OptionCount - Index) * sizeof (EFI_BOOT_MANAGER_LOAD_OPTION));
+      CopyMem (&Param->Options[Index], &Option, sizeof 
(EFI_BOOT_MANAGER_LOAD_OPTION));
+      Param->OptionCount++;
+    }
+  }
+}
+
 /**
   Returns an array of load options based on the EFI variable
   L"BootOrder"/L"DriverOrder" and the L"Boot####"/L"Driver####" variables 
impled by it.
@@ -937,16 +1024,18 @@ EfiBootManagerGetLoadOptions (
   IN EFI_BOOT_MANAGER_LOAD_OPTION_TYPE  LoadOptionType
   )
 {
-  EFI_STATUS                   Status;
-  UINT16                       *OptionOrder;
-  UINTN                        OptionOrderSize;
-  UINTN                        Index;
-  UINTN                        OptionIndex;
-  EFI_BOOT_MANAGER_LOAD_OPTION *Options;
-  CHAR16                       OptionName[BM_OPTION_NAME_LEN];
-  UINT16                       OptionNumber;
+  EFI_STATUS                    Status;
+  UINT16                        *OptionOrder;
+  UINTN                         OptionOrderSize;
+  UINTN                         Index;
+  UINTN                         OptionIndex;
+  EFI_BOOT_MANAGER_LOAD_OPTION  *Options;
+  CHAR16                        OptionName[BM_OPTION_NAME_LEN];
+  UINT16                        OptionNumber;
+  BM_COLLECT_LOAD_OPTIONS_PARAM Param;
 
   *OptionCount = 0;
+  Options      = NULL;
 
   if (LoadOptionType == LoadOptionTypeDriver || LoadOptionType == 
LoadOptionTypeSysPrep || LoadOptionType == LoadOptionTypeBoot) {
     //
@@ -987,8 +1076,16 @@ EfiBootManagerGetLoadOptions (
       *OptionCount = OptionIndex;
     }
 
-  } else {
-    return NULL;
+  } else if (LoadOptionType == LoadOptionTypePlatformRecovery) {
+    Param.OptionType = LoadOptionTypePlatformRecovery;
+    Param.Options = NULL;
+    Param.OptionCount = 0;
+    Param.Guid = &gEfiGlobalVariableGuid;
+
+    BmForEachVariable (BmCollectLoadOptions, (VOID *) &Param);
+
+    *OptionCount = Param.OptionCount;
+    Options = Param.Options;
   }
 
   return Options;
@@ -1116,7 +1213,8 @@ BmIsLoadOptionPeHeaderValid (
         if ((Type == LoadOptionTypeDriver && Subsystem == 
EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER) ||
             (Type == LoadOptionTypeDriver && Subsystem == 
EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER) ||
             (Type == LoadOptionTypeSysPrep && Subsystem == 
EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION) ||
-            (Type == LoadOptionTypeBoot && Subsystem == 
EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION)
+            (Type == LoadOptionTypeBoot && Subsystem == 
EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION) ||
+            (Type == LoadOptionTypePlatformRecovery && Subsystem == 
EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION)
             ) {
           return TRUE;
         }
diff --git a/MdeModulePkg/Library/UefiBootManagerLib/InternalBm.h 
b/MdeModulePkg/Library/UefiBootManagerLib/InternalBm.h
index 7f52b13..3fc9cc7 100644
--- a/MdeModulePkg/Library/UefiBootManagerLib/InternalBm.h
+++ b/MdeModulePkg/Library/UefiBootManagerLib/InternalBm.h
@@ -41,6 +41,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER 
EXPRESS OR IMPLIED.
 #include <Protocol/BootLogo.h>
 #include <Protocol/DriverHealth.h>
 #include <Protocol/FormBrowser2.h>
+#include <Protocol/VariableLock.h>
 
 #include <Guid/ZeroGuid.h>
 #include <Guid/MemoryTypeInformation.h>
@@ -101,7 +102,7 @@ CHAR16 *
   IN EFI_HANDLE          Handle
   );
 
-#define BM_OPTION_NAME_LEN                          sizeof ("SysPrep####")
+#define BM_OPTION_NAME_LEN                          sizeof 
("PlatformRecovery####")
 extern CHAR16  *mBmLoadOptionName[];
 
 /**
diff --git a/MdeModulePkg/Library/UefiBootManagerLib/UefiBootManagerLib.inf 
b/MdeModulePkg/Library/UefiBootManagerLib/UefiBootManagerLib.inf
index a2c6441..f1f6246 100644
--- a/MdeModulePkg/Library/UefiBootManagerLib/UefiBootManagerLib.inf
+++ b/MdeModulePkg/Library/UefiBootManagerLib/UefiBootManagerLib.inf
@@ -101,6 +101,7 @@
   gEfiDevicePathProtocolGuid                    ## CONSUMES
   gEfiBootLogoProtocolGuid                      ## CONSUMES
   gEfiSimpleTextInputExProtocolGuid             ## CONSUMES
+  gEdkiiVariableLockProtocolGuid                ## CONSUMES
   gEfiGraphicsOutputProtocolGuid                ## SOMETIMES_CONSUMES
   gEfiUsbIoProtocolGuid                         ## SOMETIMES_CONSUMES
   gEfiDiskInfoProtocolGuid                      ## SOMETIMES_CONSUMES
-- 
1.9.5.msysgit.1

_______________________________________________
edk2-devel mailing list
[email protected]
https://lists.01.org/mailman/listinfo/edk2-devel

Reply via email to