#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
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
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
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
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
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
}\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
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
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
}\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
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
//\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
//\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