23#define DEPEX_STACK_SIZE_INCREMENT 0x1000
71 Size = DEPEX_STACK_SIZE_INCREMENT;
72 if (mDepexEvaluationStack !=
NULL) {
73 Size = Size + (mDepexEvaluationStackEnd - mDepexEvaluationStack);
77 if (NewStack ==
NULL) {
78 DEBUG ((DEBUG_ERROR,
"GrowDepexStack: Cannot allocate memory for dependency evaluation stack!\n"));
79 return EFI_OUT_OF_RESOURCES;
82 if (mDepexEvaluationStack !=
NULL) {
88 mDepexEvaluationStack,
89 (mDepexEvaluationStackEnd - mDepexEvaluationStack) *
sizeof (
DEPEX_ELEMENT)
101 mDepexEvaluationStackPointer = NewStack + (mDepexEvaluationStackPointer - mDepexEvaluationStack);
102 mDepexEvaluationStack = NewStack;
103 mDepexEvaluationStackEnd = NewStack + Size;
131 if ((Type != BooleanType) && (Type != VersionType)) {
132 return EFI_INVALID_PARAMETER;
138 if (mDepexEvaluationStackPointer == mDepexEvaluationStackEnd) {
143 if (EFI_ERROR (Status)) {
148 Element.Value.Version = Value;
154 *mDepexEvaluationStackPointer = Element;
155 mDepexEvaluationStackPointer++;
180 if (mDepexEvaluationStackPointer == mDepexEvaluationStack) {
181 DEBUG ((DEBUG_ERROR,
"EvaluateDependency: Stack underflow!\n"));
182 return EFI_ACCESS_DENIED;
188 mDepexEvaluationStackPointer--;
189 *Element = *mDepexEvaluationStackPointer;
190 if ((*Element).Type != Type) {
191 DEBUG ((DEBUG_ERROR,
"EvaluateDependency: Popped element type is mismatched!\n"));
192 return EFI_INVALID_PARAMETER;
226 OUT UINT32 *LastAttemptStatus OPTIONAL
236 UINT32 LocalLastAttemptStatus;
237 UINT32 DeclaredLength;
244 if ((Dependencies ==
NULL) || (DependenciesSize == 0)) {
248 if ((FmpVersions ==
NULL) && (FmpVersionsCount > 0)) {
256 mDepexEvaluationStackPointer = mDepexEvaluationStack;
258 Iterator = (UINT8 *)Dependencies->Dependencies;
259 while (Iterator < (UINT8 *)Dependencies->Dependencies + DependenciesSize) {
262 if (Iterator +
sizeof (
EFI_GUID) >= (UINT8 *)Dependencies->Dependencies + DependenciesSize) {
263 DEBUG ((DEBUG_ERROR,
"EvaluateDependency: GUID extends beyond end of dependency expression!\n"));
264 LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_GUID_BEYOND_DEPEX;
269 Iterator = Iterator +
sizeof (
EFI_GUID);
271 for (Index = 0; Index < FmpVersionsCount; Index++) {
272 if (
CompareGuid (&FmpVersions[Index].ImageTypeId, &ImageTypeId)) {
273 Status =
Push (FmpVersions[Index].Version, VersionType);
274 if (EFI_ERROR (Status)) {
275 LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_PUSH_FAILURE;
283 if (Index == FmpVersionsCount) {
284 DEBUG ((DEBUG_ERROR,
"EvaluateDependency: %g is not found!\n", &ImageTypeId));
285 LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_FMP_NOT_FOUND;
290 case EFI_FMP_DEP_PUSH_VERSION:
291 if (Iterator +
sizeof (UINT32) >= (UINT8 *)Dependencies->Dependencies + DependenciesSize ) {
292 DEBUG ((DEBUG_ERROR,
"EvaluateDependency: VERSION extends beyond end of dependency expression!\n"));
293 LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_VERSION_BEYOND_DEPEX;
297 Version = *(UINT32 *)(Iterator + 1);
298 Status =
Push (Version, VersionType);
299 if (EFI_ERROR (Status)) {
300 LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_PUSH_FAILURE;
304 Iterator = Iterator +
sizeof (UINT32);
306 case EFI_FMP_DEP_VERSION_STR:
307 Iterator +=
AsciiStrnLenS ((CHAR8 *)Iterator, DependenciesSize - (Iterator - Dependencies->Dependencies));
308 if (Iterator == (UINT8 *)Dependencies->Dependencies + DependenciesSize) {
309 DEBUG ((DEBUG_ERROR,
"EvaluateDependency: STRING extends beyond end of dependency expression!\n"));
310 LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_VERSION_STR_BEYOND_DEPEX;
315 case EFI_FMP_DEP_AND:
316 Status =
Pop (&Element1, BooleanType);
317 if (EFI_ERROR (Status)) {
318 LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_POP_FAILURE;
322 Status =
Pop (&Element2, BooleanType);
323 if (EFI_ERROR (Status)) {
324 LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_POP_FAILURE;
328 Status =
Push (Element1.Value.Boolean & Element2.Value.Boolean, BooleanType);
329 if (EFI_ERROR (Status)) {
330 LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_PUSH_FAILURE;
336 Status =
Pop (&Element1, BooleanType);
337 if (EFI_ERROR (Status)) {
338 LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_POP_FAILURE;
342 Status =
Pop (&Element2, BooleanType);
343 if (EFI_ERROR (Status)) {
344 LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_POP_FAILURE;
348 Status =
Push (Element1.Value.Boolean | Element2.Value.Boolean, BooleanType);
349 if (EFI_ERROR (Status)) {
350 LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_PUSH_FAILURE;
355 case EFI_FMP_DEP_NOT:
356 Status =
Pop (&Element1, BooleanType);
357 if (EFI_ERROR (Status)) {
358 LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_POP_FAILURE;
362 Status =
Push (!(Element1.Value.Boolean), BooleanType);
363 if (EFI_ERROR (Status)) {
364 LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_PUSH_FAILURE;
369 case EFI_FMP_DEP_TRUE:
371 if (EFI_ERROR (Status)) {
372 LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_PUSH_FAILURE;
377 case EFI_FMP_DEP_FALSE:
379 if (EFI_ERROR (Status)) {
380 LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_PUSH_FAILURE;
386 Status =
Pop (&Element1, VersionType);
387 if (EFI_ERROR (Status)) {
388 LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_POP_FAILURE;
392 Status =
Pop (&Element2, VersionType);
393 if (EFI_ERROR (Status)) {
394 LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_POP_FAILURE;
398 Status = (Element1.Value.Version == Element2.Value.Version) ?
Push (
TRUE, BooleanType) :
Push (
FALSE, BooleanType);
399 if (EFI_ERROR (Status)) {
400 LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_PUSH_FAILURE;
406 Status =
Pop (&Element1, VersionType);
407 if (EFI_ERROR (Status)) {
408 LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_POP_FAILURE;
412 Status =
Pop (&Element2, VersionType);
413 if (EFI_ERROR (Status)) {
414 LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_POP_FAILURE;
418 Status = (Element1.Value.Version > Element2.Value.Version) ?
Push (
TRUE, BooleanType) :
Push (
FALSE, BooleanType);
419 if (EFI_ERROR (Status)) {
420 LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_PUSH_FAILURE;
425 case EFI_FMP_DEP_GTE:
426 Status =
Pop (&Element1, VersionType);
427 if (EFI_ERROR (Status)) {
428 LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_POP_FAILURE;
432 Status =
Pop (&Element2, VersionType);
433 if (EFI_ERROR (Status)) {
434 LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_POP_FAILURE;
438 Status = (Element1.Value.Version >= Element2.Value.Version) ?
Push (
TRUE, BooleanType) :
Push (
FALSE, BooleanType);
439 if (EFI_ERROR (Status)) {
440 LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_PUSH_FAILURE;
446 Status =
Pop (&Element1, VersionType);
447 if (EFI_ERROR (Status)) {
448 LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_POP_FAILURE;
452 Status =
Pop (&Element2, VersionType);
453 if (EFI_ERROR (Status)) {
454 LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_POP_FAILURE;
458 Status = (Element1.Value.Version < Element2.Value.Version) ?
Push (
TRUE, BooleanType) :
Push (
FALSE, BooleanType);
459 if (EFI_ERROR (Status)) {
460 LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_PUSH_FAILURE;
465 case EFI_FMP_DEP_LTE:
466 Status =
Pop (&Element1, VersionType);
467 if (EFI_ERROR (Status)) {
468 LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_POP_FAILURE;
472 Status =
Pop (&Element2, VersionType);
473 if (EFI_ERROR (Status)) {
474 LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_POP_FAILURE;
478 Status = (Element1.Value.Version <= Element2.Value.Version) ?
Push (
TRUE, BooleanType) :
Push (
FALSE, BooleanType);
479 if (EFI_ERROR (Status)) {
480 LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_PUSH_FAILURE;
485 case EFI_FMP_DEP_END:
486 Status =
Pop (&Element1, BooleanType);
487 if (EFI_ERROR (Status)) {
488 LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_POP_FAILURE;
492 return Element1.Value.Boolean;
493 case EFI_FMP_DEP_DECLARE_LENGTH:
494 if (Iterator +
sizeof (UINT32) >= (UINT8 *)Dependencies->Dependencies + DependenciesSize ) {
495 DEBUG ((DEBUG_ERROR,
"EvaluateDependency: DECLARE_LENGTH extends beyond end of dependency expression!\n"));
496 LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_DECLARE_LENGTH_BEYOND_DEPEX;
503 if (Iterator != Dependencies->Dependencies) {
504 DEBUG ((DEBUG_ERROR,
"EvaluateDependency: DECLARE_LENGTH is not the first opcode!\n"));
505 LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_DECLARE_LENGTH_NOT_FIRST_OPCODE;
509 DeclaredLength = *(UINT32 *)(Iterator + 1);
510 if (DeclaredLength != DependenciesSize) {
511 DEBUG ((DEBUG_ERROR,
"EvaluateDependency: DECLARE_LENGTH is not equal to length of dependency expression!\n"));
512 LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_DECLARE_LENGTH_INCORRECT;
516 Status =
Push (DeclaredLength, VersionType);
517 if (EFI_ERROR (Status)) {
518 LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_PUSH_FAILURE;
522 Iterator = Iterator +
sizeof (UINT32);
525 DEBUG ((DEBUG_ERROR,
"EvaluateDependency: Unknown Opcode - %02x!\n", *Iterator));
526 LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_UNKNOWN_OPCODE;
533 DEBUG ((DEBUG_ERROR,
"EvaluateDependency: No EFI_FMP_DEP_END Opcode in expression!\n"));
534 LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_NO_END_OPCODE;
537 if (LastAttemptStatus !=
NULL) {
538 *LastAttemptStatus = LocalLastAttemptStatus;
564 OUT UINT32 *DepexSize,
565 OUT UINT32 *LastAttemptStatus OPTIONAL
570 if (DepexSize !=
NULL) {
574 if (Dependencies ==
NULL) {
578 Depex = Dependencies->Dependencies;
579 while (Depex < Dependencies->Dependencies + MaxDepexSize) {
584 case EFI_FMP_DEP_PUSH_VERSION:
585 Depex +=
sizeof (UINT32) + 1;
587 case EFI_FMP_DEP_VERSION_STR:
588 Depex +=
AsciiStrnLenS ((CHAR8 *)Depex, Dependencies->Dependencies + MaxDepexSize - Depex) + 1;
590 case EFI_FMP_DEP_AND:
592 case EFI_FMP_DEP_NOT:
593 case EFI_FMP_DEP_TRUE:
594 case EFI_FMP_DEP_FALSE:
597 case EFI_FMP_DEP_GTE:
599 case EFI_FMP_DEP_LTE:
602 case EFI_FMP_DEP_END:
604 if (DepexSize !=
NULL) {
605 *DepexSize = (UINT32)(Depex - Dependencies->Dependencies);
609 case EFI_FMP_DEP_DECLARE_LENGTH:
610 Depex +=
sizeof (UINT32) + 1;
617 if (LastAttemptStatus !=
NULL) {
618 *LastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_NO_END_OPCODE;
643 OUT UINT32 *DepexSize,
644 OUT UINT32 *LastAttemptStatus OPTIONAL
657 if ((((
UINTN)Image +
sizeof (Image->MonotonicCount) + Image->AuthInfo.Hdr.dwLength) < (
UINTN)Image) || \
658 (((
UINTN)Image + sizeof (Image->MonotonicCount) + Image->AuthInfo.Hdr.dwLength) >= (
UINTN)Image + ImageSize))
663 if (LastAttemptStatus !=
NULL) {
670 Depex = (
EFI_FIRMWARE_IMAGE_DEP *)((UINT8 *)Image +
sizeof (Image->MonotonicCount) + Image->AuthInfo.Hdr.dwLength);
671 MaxDepexSize = ImageSize - (
sizeof (Image->MonotonicCount) + Image->AuthInfo.Hdr.dwLength);
UINTN EFIAPI AsciiStrnLenS(IN CONST CHAR8 *String, IN UINTN MaxSize)
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
BOOLEAN EFIAPI CompareGuid(IN CONST GUID *Guid1, IN CONST GUID *Guid2)
GUID *EFIAPI CopyGuid(OUT GUID *DestinationGuid, IN CONST GUID *SourceGuid)
VOID EFIAPI FreePool(IN VOID *Buffer)
#define EFI_FMP_DEP_PUSH_GUID
EFI_STATUS Push(IN UINT32 Value, IN UINTN Type)
EFI_STATUS GrowDepexStack(VOID)
BOOLEAN EFIAPI EvaluateDependency(IN EFI_FIRMWARE_IMAGE_DEP *Dependencies, IN UINTN DependenciesSize, IN FMP_DEPEX_CHECK_VERSION_DATA *FmpVersions OPTIONAL, IN UINTN FmpVersionsCount, OUT UINT32 *LastAttemptStatus OPTIONAL)
BOOLEAN EFIAPI ValidateDependency(IN EFI_FIRMWARE_IMAGE_DEP *Dependencies, IN UINTN MaxDepexSize, OUT UINT32 *DepexSize, OUT UINT32 *LastAttemptStatus OPTIONAL)
EFI_FIRMWARE_IMAGE_DEP *EFIAPI GetImageDependency(IN EFI_FIRMWARE_IMAGE_AUTHENTICATION *Image, IN UINTN ImageSize, OUT UINT32 *DepexSize, OUT UINT32 *LastAttemptStatus OPTIONAL)
EFI_STATUS Pop(OUT DEPEX_ELEMENT *Element, IN ELEMENT_TYPE Type)
@ LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_GET_DEPEX_FAILURE
#define DEBUG(Expression)
VOID *EFIAPI AllocatePool(IN UINTN AllocationSize)
#define LAST_ATTEMPT_STATUS_SUCCESS