]> git.proxmox.com Git - mirror_edk2.git/blobdiff - FmpDevicePkg/Library/FmpDependencyLib/FmpDependencyLib.c
FmpDevicePkg: Add Last Attempt Status support to dependency libs
[mirror_edk2.git] / FmpDevicePkg / Library / FmpDependencyLib / FmpDependencyLib.c
index 5ef25d2415cf5c59910d1cab6922406aea19c99d..b222ace6d6ca20d90a495bbda90769b39ecbe3e6 100644 (file)
@@ -13,6 +13,9 @@
 #include <Library/DebugLib.h>\r
 #include <Library/FmpDependencyLib.h>\r
 #include <Library/MemoryAllocationLib.h>\r
+#include <Guid/SystemResourceTable.h>\r
+#include <LastAttemptStatus.h>\r
+#include <FmpLastAttemptStatus.h>\r
 \r
 //\r
 // Define the initial size of the dependency expression evaluation stack\r
@@ -203,6 +206,10 @@ Pop (
                                   parameter is optional and can be set to NULL.\r
   @param[in]   FmpVersionsCount   Element count of the array. When FmpVersions\r
                                   is NULL, FmpVersionsCount must be 0.\r
+  @param[out]  LastAttemptStatus  An optional pointer to a UINT32 that holds the\r
+                                  last attempt status to report back to the caller.\r
+                                  This function will set the value to LAST_ATTEMPT_STATUS_SUCCESS\r
+                                  if an error code is not set.\r
 \r
   @retval TRUE    Dependency expressions evaluate to TRUE.\r
   @retval FALSE   Dependency expressions evaluate to FALSE.\r
@@ -211,10 +218,11 @@ Pop (
 BOOLEAN\r
 EFIAPI\r
 EvaluateDependency (\r
-  IN EFI_FIRMWARE_IMAGE_DEP        *Dependencies,\r
-  IN UINTN                         DependenciesSize,\r
-  IN FMP_DEPEX_CHECK_VERSION_DATA  *FmpVersions      OPTIONAL,\r
-  IN UINTN                         FmpVersionsCount\r
+  IN  EFI_FIRMWARE_IMAGE_DEP        *Dependencies,\r
+  IN  UINTN                         DependenciesSize,\r
+  IN  FMP_DEPEX_CHECK_VERSION_DATA  *FmpVersions,      OPTIONAL\r
+  IN  UINTN                         FmpVersionsCount,\r
+  OUT UINT32                        *LastAttemptStatus OPTIONAL\r
   )\r
 {\r
   EFI_STATUS                        Status;\r
@@ -224,6 +232,9 @@ EvaluateDependency (
   DEPEX_ELEMENT                     Element2;\r
   GUID                              ImageTypeId;\r
   UINT32                            Version;\r
+  UINT32                            LocalLastAttemptStatus;\r
+\r
+  LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_SUCCESS;\r
 \r
   //\r
   // Check if parameter is valid.\r
@@ -249,6 +260,7 @@ EvaluateDependency (
     case EFI_FMP_DEP_PUSH_GUID:\r
       if (Iterator + sizeof (EFI_GUID) >= (UINT8 *) Dependencies->Dependencies + DependenciesSize) {\r
         DEBUG ((DEBUG_ERROR, "EvaluateDependency: GUID extends beyond end of dependency expression!\n"));\r
+        LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_GUID_BEYOND_DEPEX;\r
         goto Error;\r
       }\r
 \r
@@ -259,6 +271,7 @@ EvaluateDependency (
         if(CompareGuid (&FmpVersions[Index].ImageTypeId, &ImageTypeId)){\r
           Status = Push (FmpVersions[Index].Version, VersionType);\r
           if (EFI_ERROR (Status)) {\r
+            LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_PUSH_FAILURE;\r
             goto Error;\r
           }\r
           break;\r
@@ -266,18 +279,21 @@ EvaluateDependency (
       }\r
       if (Index == FmpVersionsCount) {\r
         DEBUG ((DEBUG_ERROR, "EvaluateDependency: %g is not found!\n", &ImageTypeId));\r
+        LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_FMP_NOT_FOUND;\r
         goto Error;\r
       }\r
       break;\r
     case EFI_FMP_DEP_PUSH_VERSION:\r
       if (Iterator + sizeof (UINT32) >= (UINT8 *) Dependencies->Dependencies + DependenciesSize ) {\r
         DEBUG ((DEBUG_ERROR, "EvaluateDependency: VERSION extends beyond end of dependency expression!\n"));\r
+        LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_VERSION_BEYOND_DEPEX;\r
         goto Error;\r
       }\r
 \r
       Version = *(UINT32 *) (Iterator + 1);\r
       Status = Push (Version, VersionType);\r
       if (EFI_ERROR (Status)) {\r
+        LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_PUSH_FAILURE;\r
         goto Error;\r
       }\r
       Iterator = Iterator + sizeof (UINT32);\r
@@ -286,154 +302,191 @@ EvaluateDependency (
       Iterator += AsciiStrnLenS ((CHAR8 *) Iterator, DependenciesSize - (Iterator - Dependencies->Dependencies));\r
       if (Iterator == (UINT8 *) Dependencies->Dependencies + DependenciesSize) {\r
         DEBUG ((DEBUG_ERROR, "EvaluateDependency: STRING extends beyond end of dependency expression!\n"));\r
+        LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_VERSION_STR_BEYOND_DEPEX;\r
         goto Error;\r
       }\r
       break;\r
     case EFI_FMP_DEP_AND:\r
       Status = Pop (&Element1, BooleanType);\r
       if (EFI_ERROR (Status)) {\r
+        LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_POP_FAILURE;\r
         goto Error;\r
       }\r
       Status = Pop (&Element2, BooleanType);\r
       if (EFI_ERROR (Status)) {\r
+        LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_POP_FAILURE;\r
         goto Error;\r
       }\r
       Status = Push (Element1.Value.Boolean & Element2.Value.Boolean, BooleanType);\r
       if (EFI_ERROR (Status)) {\r
+        LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_PUSH_FAILURE;\r
         goto Error;\r
       }\r
       break;\r
     case EFI_FMP_DEP_OR:\r
       Status = Pop (&Element1, BooleanType);\r
       if (EFI_ERROR (Status)) {\r
+        LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_POP_FAILURE;\r
         goto Error;\r
       }\r
       Status = Pop(&Element2, BooleanType);\r
       if (EFI_ERROR (Status)) {\r
+        LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_POP_FAILURE;\r
         goto Error;\r
       }\r
       Status = Push (Element1.Value.Boolean | Element2.Value.Boolean, BooleanType);\r
       if (EFI_ERROR (Status)) {\r
+        LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_PUSH_FAILURE;\r
         goto Error;\r
       }\r
       break;\r
     case EFI_FMP_DEP_NOT:\r
       Status = Pop (&Element1, BooleanType);\r
       if (EFI_ERROR (Status)) {\r
+        LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_POP_FAILURE;\r
         goto Error;\r
       }\r
       Status = Push (!(Element1.Value.Boolean), BooleanType);\r
       if (EFI_ERROR (Status)) {\r
+        LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_PUSH_FAILURE;\r
         goto Error;\r
       }\r
       break;\r
     case EFI_FMP_DEP_TRUE:\r
       Status = Push (TRUE, BooleanType);\r
       if (EFI_ERROR (Status)) {\r
+        LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_PUSH_FAILURE;\r
         goto Error;\r
       }\r
       break;\r
     case EFI_FMP_DEP_FALSE:\r
       Status = Push (FALSE, BooleanType);\r
       if (EFI_ERROR (Status)) {\r
+        LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_PUSH_FAILURE;\r
         goto Error;\r
       }\r
       break;\r
     case EFI_FMP_DEP_EQ:\r
       Status = Pop (&Element1, VersionType);\r
       if (EFI_ERROR (Status)) {\r
+        LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_POP_FAILURE;\r
         goto Error;\r
       }\r
       Status = Pop (&Element2, VersionType);\r
       if (EFI_ERROR (Status)) {\r
+        LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_POP_FAILURE;\r
         goto Error;\r
       }\r
       Status = (Element1.Value.Version == Element2.Value.Version) ? Push (TRUE, BooleanType) : Push (FALSE, BooleanType);\r
       if (EFI_ERROR (Status)) {\r
+        LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_PUSH_FAILURE;\r
         goto Error;\r
       }\r
       break;\r
     case EFI_FMP_DEP_GT:\r
       Status = Pop (&Element1, VersionType);\r
       if (EFI_ERROR (Status)) {\r
+        LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_POP_FAILURE;\r
         goto Error;\r
       }\r
       Status = Pop (&Element2, VersionType);\r
       if (EFI_ERROR (Status)) {\r
+        LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_POP_FAILURE;\r
         goto Error;\r
       }\r
       Status = (Element1.Value.Version >  Element2.Value.Version) ? Push (TRUE, BooleanType) : Push (FALSE, BooleanType);\r
       if (EFI_ERROR (Status)) {\r
+        LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_PUSH_FAILURE;\r
         goto Error;\r
       }\r
       break;\r
     case EFI_FMP_DEP_GTE:\r
       Status = Pop (&Element1, VersionType);\r
       if (EFI_ERROR (Status)) {\r
+        LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_POP_FAILURE;\r
         goto Error;\r
       }\r
       Status = Pop (&Element2, VersionType);\r
       if (EFI_ERROR (Status)) {\r
+        LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_POP_FAILURE;\r
         goto Error;\r
       }\r
       Status = (Element1.Value.Version >= Element2.Value.Version) ? Push (TRUE, BooleanType) : Push (FALSE, BooleanType);\r
       if (EFI_ERROR (Status)) {\r
+        LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_PUSH_FAILURE;\r
         goto Error;\r
       }\r
       break;\r
     case EFI_FMP_DEP_LT:\r
       Status = Pop (&Element1, VersionType);\r
       if (EFI_ERROR (Status)) {\r
+        LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_POP_FAILURE;\r
         goto Error;\r
       }\r
       Status = Pop (&Element2, VersionType);\r
       if (EFI_ERROR (Status)) {\r
+        LocalLastAttemptStatus= LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_POP_FAILURE;\r
         goto Error;\r
       }\r
       Status = (Element1.Value.Version <  Element2.Value.Version) ? Push (TRUE, BooleanType) : Push (FALSE, BooleanType);\r
       if (EFI_ERROR (Status)) {\r
+        LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_PUSH_FAILURE;\r
         goto Error;\r
       }\r
       break;\r
     case EFI_FMP_DEP_LTE:\r
       Status = Pop (&Element1, VersionType);\r
       if (EFI_ERROR (Status)) {\r
+        LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_POP_FAILURE;\r
         goto Error;\r
       }\r
       Status = Pop (&Element2, VersionType);\r
       if (EFI_ERROR (Status)) {\r
+        LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_POP_FAILURE;\r
         goto Error;\r
       }\r
       Status = (Element1.Value.Version <= Element2.Value.Version) ? Push (TRUE, BooleanType) : Push (FALSE, BooleanType);\r
       if (EFI_ERROR (Status)) {\r
+        LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_PUSH_FAILURE;\r
         goto Error;\r
       }\r
       break;\r
     case EFI_FMP_DEP_END:\r
       Status = Pop (&Element1, BooleanType);\r
       if (EFI_ERROR (Status)) {\r
+        LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_POP_FAILURE;\r
         goto Error;\r
       }\r
       return Element1.Value.Boolean;\r
     default:\r
       DEBUG ((DEBUG_ERROR, "EvaluateDependency: Unknown Opcode - %02x!\n", *Iterator));\r
+      LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_UNKNOWN_OPCODE;\r
       goto Error;\r
     }\r
     Iterator++;\r
   }\r
 \r
   DEBUG ((DEBUG_ERROR, "EvaluateDependency: No EFI_FMP_DEP_END Opcode in expression!\n"));\r
+  LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_NO_END_OPCODE;\r
 \r
 Error:\r
+  if (LastAttemptStatus != NULL) {\r
+    *LastAttemptStatus = LocalLastAttemptStatus;\r
+  }\r
+\r
   return FALSE;\r
 }\r
 \r
 /**\r
   Validate the dependency expression and output its size.\r
 \r
-  @param[in]   Dependencies   Pointer to the EFI_FIRMWARE_IMAGE_DEP.\r
-  @param[in]   MaxDepexSize   Max size of the dependency.\r
-  @param[out]  DepexSize      Size of dependency.\r
+  @param[in]   Dependencies       Pointer to the EFI_FIRMWARE_IMAGE_DEP.\r
+  @param[in]   MaxDepexSize       Max size of the dependency.\r
+  @param[out]  DepexSize          Size of dependency.\r
+  @param[out]  LastAttemptStatus  An optional pointer to a UINT32 that holds the\r
+                                  last attempt status to report back to the caller.\r
+                                  If a last attempt status error code is not returned,\r
+                                  this function will not modify the LastAttemptStatus value.\r
 \r
   @retval TRUE    The dependency expression is valid.\r
   @retval FALSE   The dependency expression is invalid.\r
@@ -444,7 +497,8 @@ EFIAPI
 ValidateDependency (\r
   IN  EFI_FIRMWARE_IMAGE_DEP  *Dependencies,\r
   IN  UINTN                   MaxDepexSize,\r
-  OUT UINT32                  *DepexSize\r
+  OUT UINT32                  *DepexSize,\r
+  OUT UINT32                  *LastAttemptStatus OPTIONAL\r
   )\r
 {\r
   UINT8  *Depex;\r
@@ -493,16 +547,23 @@ ValidateDependency (
     }\r
   }\r
 \r
+  if (LastAttemptStatus != NULL) {\r
+    *LastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_NO_END_OPCODE;\r
+  }\r
+\r
   return FALSE;\r
 }\r
 \r
 /**\r
   Get dependency from firmware image.\r
 \r
-  @param[in]  Image       Points to the firmware image.\r
-  @param[in]  ImageSize   Size, in bytes, of the firmware image.\r
-  @param[out] DepexSize   Size, in bytes, of the dependency.\r
-\r
+  @param[in]  Image               Points to the firmware image.\r
+  @param[in]  ImageSize           Size, in bytes, of the firmware image.\r
+  @param[out] DepexSize           Size, in bytes, of the dependency.\r
+  @param[out] LastAttemptStatus   An optional pointer to a UINT32 that holds the\r
+                                  last attempt status to report back to the caller.\r
+                                  If a last attempt status error code is not returned,\r
+                                  this function will not modify the LastAttemptStatus value.\r
   @retval  The pointer to dependency.\r
   @retval  Null\r
 \r
@@ -512,7 +573,8 @@ EFIAPI
 GetImageDependency (\r
   IN  EFI_FIRMWARE_IMAGE_AUTHENTICATION *Image,\r
   IN  UINTN                             ImageSize,\r
-  OUT UINT32                            *DepexSize\r
+  OUT UINT32                            *DepexSize,\r
+  OUT UINT32                            *LastAttemptStatus  OPTIONAL\r
   )\r
 {\r
   EFI_FIRMWARE_IMAGE_DEP *Depex;\r
@@ -530,6 +592,9 @@ GetImageDependency (
     //\r
     // Pointer overflow. Invalid image.\r
     //\r
+    if (LastAttemptStatus != NULL) {\r
+      *LastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_GET_DEPEX_FAILURE;\r
+    }\r
     return NULL;\r
   }\r
 \r
@@ -539,7 +604,7 @@ GetImageDependency (
   //\r
   // Validate the dependency and get the size of dependency\r
   //\r
-  if (ValidateDependency (Depex, MaxDepexSize, DepexSize)) {\r
+  if (ValidateDependency (Depex, MaxDepexSize, DepexSize, LastAttemptStatus)) {\r
     return Depex;\r
   }\r
 \r