]> git.proxmox.com Git - mirror_edk2.git/blame - FmpDevicePkg/FmpDxe/Dependency.c
FmpDevicePkg: Add FmpDependencyDevice library class and NULL instance
[mirror_edk2.git] / FmpDevicePkg / FmpDxe / Dependency.c
CommitLineData
2ed845b3
WX
1/** @file\r
2 Supports Capsule Dependency Expression.\r
3\r
4 Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>\r
5\r
6 SPDX-License-Identifier: BSD-2-Clause-Patent\r
7\r
8**/\r
9#include "FmpDxe.h"\r
10#include "Dependency.h"\r
11\r
12//\r
13// Define the initial size of the dependency expression evaluation stack\r
14//\r
15#define DEPEX_STACK_SIZE_INCREMENT 0x1000\r
16\r
17//\r
18// Type of stack element\r
19//\r
20typedef enum {\r
21 BooleanType,\r
22 VersionType\r
23} ELEMENT_TYPE;\r
24\r
25//\r
26// Value of stack element\r
27//\r
28typedef union {\r
29 BOOLEAN Boolean;\r
30 UINT32 Version;\r
31} ELEMENT_VALUE;\r
32\r
33//\r
34// Stack element used to evaluate dependency expressions\r
35//\r
36typedef struct {\r
37 ELEMENT_VALUE Value;\r
38 ELEMENT_TYPE Type;\r
39} DEPEX_ELEMENT;\r
40\r
41//\r
42// Global variable used to support dependency evaluation\r
43//\r
44UINTN mNumberOfFmpInstance = 0;\r
45EFI_FIRMWARE_IMAGE_DESCRIPTOR **mFmpImageInfoBuf = NULL;\r
46\r
47//\r
48// Indicates the status of dependency check, default value is DEPENDENCIES_SATISFIED.\r
49//\r
50UINT8 mDependenciesCheckStatus = DEPENDENCIES_SATISFIED;\r
51\r
52//\r
53// Global stack used to evaluate dependency expressions\r
54//\r
55DEPEX_ELEMENT *mDepexEvaluationStack = NULL;\r
56DEPEX_ELEMENT *mDepexEvaluationStackEnd = NULL;\r
57DEPEX_ELEMENT *mDepexEvaluationStackPointer = NULL;\r
58\r
59/**\r
60 Grow size of the Depex stack\r
61\r
62 @retval EFI_SUCCESS Stack successfully growed.\r
63 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.\r
64\r
65**/\r
66EFI_STATUS\r
67GrowDepexStack (\r
68 VOID\r
69 )\r
70{\r
71 DEPEX_ELEMENT *NewStack;\r
72 UINTN Size;\r
73\r
74 Size = DEPEX_STACK_SIZE_INCREMENT;\r
75 if (mDepexEvaluationStack != NULL) {\r
76 Size = Size + (mDepexEvaluationStackEnd - mDepexEvaluationStack);\r
77 }\r
78\r
79 NewStack = AllocatePool (Size * sizeof (DEPEX_ELEMENT));\r
80 if (NewStack == NULL) {\r
81 return EFI_OUT_OF_RESOURCES;\r
82 }\r
83\r
84 if (mDepexEvaluationStack != NULL) {\r
85 //\r
86 // Copy to Old Stack to the New Stack\r
87 //\r
88 CopyMem (\r
89 NewStack,\r
90 mDepexEvaluationStack,\r
91 (mDepexEvaluationStackEnd - mDepexEvaluationStack) * sizeof (DEPEX_ELEMENT)\r
92 );\r
93\r
94 //\r
95 // Free The Old Stack\r
96 //\r
97 FreePool (mDepexEvaluationStack);\r
98 }\r
99\r
100 //\r
101 // Make the Stack pointer point to the old data in the new stack\r
102 //\r
103 mDepexEvaluationStackPointer = NewStack + (mDepexEvaluationStackPointer - mDepexEvaluationStack);\r
104 mDepexEvaluationStack = NewStack;\r
105 mDepexEvaluationStackEnd = NewStack + Size;\r
106\r
107 return EFI_SUCCESS;\r
108}\r
109\r
110/**\r
111 Push an element onto the Stack.\r
112\r
113 @param[in] Value Value to push.\r
114 @param[in] Type Element Type\r
115\r
116 @retval EFI_SUCCESS The value was pushed onto the stack.\r
117 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.\r
118 @retval EFI_INVALID_PARAMETER Wrong stack element type.\r
119\r
120**/\r
121EFI_STATUS\r
122Push (\r
123 IN UINT32 Value,\r
124 IN UINTN Type\r
125 )\r
126{\r
127 EFI_STATUS Status;\r
128 DEPEX_ELEMENT Element;\r
129\r
130 //\r
131 // Check Type\r
132 //\r
133 if (Type != BooleanType && Type != VersionType) {\r
134 return EFI_INVALID_PARAMETER;\r
135 }\r
136\r
137 //\r
138 // Check for a stack overflow condition\r
139 //\r
140 if (mDepexEvaluationStackPointer == mDepexEvaluationStackEnd) {\r
141 //\r
142 // Grow the stack\r
143 //\r
144 Status = GrowDepexStack ();\r
145 if (EFI_ERROR (Status)) {\r
146 return Status;\r
147 }\r
148 }\r
149\r
150 Element.Value.Version = Value;\r
151 Element.Type = Type;\r
152\r
153 //\r
154 // Push the item onto the stack\r
155 //\r
156 *mDepexEvaluationStackPointer = Element;\r
157 mDepexEvaluationStackPointer++;\r
158\r
159 return EFI_SUCCESS;\r
160}\r
161\r
162\r
163/**\r
164 Pop an element from the stack.\r
165\r
466b877f
G
166 @param[out] Element Element to pop.\r
167 @param[in] Type Type of element.\r
2ed845b3
WX
168\r
169 @retval EFI_SUCCESS The value was popped onto the stack.\r
170 @retval EFI_ACCESS_DENIED The pop operation underflowed the stack.\r
171 @retval EFI_INVALID_PARAMETER Type is mismatched.\r
172\r
173**/\r
174EFI_STATUS\r
175Pop (\r
176 OUT DEPEX_ELEMENT *Element,\r
177 IN ELEMENT_TYPE Type\r
178 )\r
179{\r
180 //\r
181 // Check for a stack underflow condition\r
182 //\r
183 if (mDepexEvaluationStackPointer == mDepexEvaluationStack) {\r
184 return EFI_ACCESS_DENIED;\r
185 }\r
186\r
187 //\r
188 // Pop the item off the stack\r
189 //\r
190 mDepexEvaluationStackPointer--;\r
191 *Element = *mDepexEvaluationStackPointer;\r
192 if ((*Element).Type != Type) {\r
193 return EFI_INVALID_PARAMETER;\r
194 }\r
195 return EFI_SUCCESS;\r
196}\r
197\r
198/**\r
199 Evaluate the dependencies.\r
200\r
201 @param[in] Dependencies Dependency expressions.\r
202 @param[in] DependenciesSize Size of Dependency expressions.\r
203\r
204 @retval TRUE Dependency expressions evaluate to TRUE.\r
205 @retval FALSE Dependency expressions evaluate to FALSE.\r
206\r
207**/\r
208BOOLEAN\r
209EvaluateDependencies (\r
210 IN CONST EFI_FIRMWARE_IMAGE_DEP * Dependencies,\r
211 IN CONST UINTN DependenciesSize\r
212 )\r
213{\r
214 EFI_STATUS Status;\r
215 UINT8 *Iterator;\r
216 UINT8 Index;\r
217 DEPEX_ELEMENT Element1;\r
218 DEPEX_ELEMENT Element2;\r
219 GUID ImageTypeId;\r
220 UINT32 Version;\r
221\r
222 if (Dependencies == NULL || DependenciesSize == 0) {\r
223 return FALSE;\r
224 }\r
225\r
226 //\r
227 // Clean out memory leaks in Depex Boolean stack. Leaks are only caused by\r
228 // incorrectly formed DEPEX expressions\r
229 //\r
230 mDepexEvaluationStackPointer = mDepexEvaluationStack;\r
231\r
232 Iterator = (UINT8 *) Dependencies->Dependencies;\r
233 while (Iterator < (UINT8 *) Dependencies->Dependencies + DependenciesSize) {\r
234 switch (*Iterator)\r
235 {\r
236 case EFI_FMP_DEP_PUSH_GUID:\r
237 if (Iterator + sizeof (EFI_GUID) >= (UINT8 *) Dependencies->Dependencies + DependenciesSize) {\r
238 Status = EFI_INVALID_PARAMETER;\r
239 goto Error;\r
240 }\r
241\r
242 CopyGuid (&ImageTypeId, (EFI_GUID *) (Iterator + 1));\r
243 Iterator = Iterator + sizeof (EFI_GUID);\r
244\r
245 for (Index = 0; Index < mNumberOfFmpInstance; Index ++){\r
246 if (mFmpImageInfoBuf[Index] == NULL) {\r
247 continue;\r
248 }\r
249 if(CompareGuid (&mFmpImageInfoBuf[Index]->ImageTypeId, &ImageTypeId)){\r
250 Status = Push (mFmpImageInfoBuf[Index]->Version, VersionType);\r
251 if (EFI_ERROR (Status)) {\r
252 goto Error;\r
253 }\r
254 break;\r
255 }\r
256 }\r
257 if (Index == mNumberOfFmpInstance) {\r
258 Status = EFI_NOT_FOUND;\r
259 goto Error;\r
260 }\r
261 break;\r
262 case EFI_FMP_DEP_PUSH_VERSION:\r
263 if (Iterator + sizeof (UINT32) >= (UINT8 *) Dependencies->Dependencies + DependenciesSize ) {\r
264 Status = EFI_INVALID_PARAMETER;\r
265 goto Error;\r
266 }\r
267\r
268 Version = *(UINT32 *) (Iterator + 1);\r
269 Status = Push (Version, VersionType);\r
270 if (EFI_ERROR (Status)) {\r
271 goto Error;\r
272 }\r
273 Iterator = Iterator + sizeof (UINT32);\r
274 break;\r
275 case EFI_FMP_DEP_VERSION_STR:\r
276 Iterator += AsciiStrnLenS ((CHAR8 *) Iterator, DependenciesSize - (Iterator - Dependencies->Dependencies));\r
277 break;\r
278 case EFI_FMP_DEP_AND:\r
279 Status = Pop (&Element1, BooleanType);\r
280 if (EFI_ERROR (Status)) {\r
281 goto Error;\r
282 }\r
283 Status = Pop (&Element2, BooleanType);\r
284 if (EFI_ERROR (Status)) {\r
285 goto Error;\r
286 }\r
287 Status = Push (Element1.Value.Boolean & Element2.Value.Boolean, BooleanType);\r
288 if (EFI_ERROR (Status)) {\r
289 goto Error;\r
290 }\r
291 break;\r
292 case EFI_FMP_DEP_OR:\r
293 Status = Pop (&Element1, BooleanType);\r
294 if (EFI_ERROR (Status)) {\r
295 goto Error;\r
296 }\r
297 Status = Pop(&Element2, BooleanType);\r
298 if (EFI_ERROR (Status)) {\r
299 goto Error;\r
300 }\r
301 Status = Push (Element1.Value.Boolean | Element2.Value.Boolean, BooleanType);\r
302 if (EFI_ERROR (Status)) {\r
303 goto Error;\r
304 }\r
305 break;\r
306 case EFI_FMP_DEP_NOT:\r
307 Status = Pop (&Element1, BooleanType);\r
308 if (EFI_ERROR (Status)) {\r
309 goto Error;\r
310 }\r
311 Status = Push (!(Element1.Value.Boolean), BooleanType);\r
312 if (EFI_ERROR (Status)) {\r
313 goto Error;\r
314 }\r
315 break;\r
316 case EFI_FMP_DEP_TRUE:\r
317 Status = Push (TRUE, BooleanType);\r
318 if (EFI_ERROR (Status)) {\r
319 goto Error;\r
320 }\r
321 break;\r
322 case EFI_FMP_DEP_FALSE:\r
323 Status = Push (FALSE, BooleanType);\r
324 if (EFI_ERROR (Status)) {\r
325 goto Error;\r
326 }\r
327 break;\r
328 case EFI_FMP_DEP_EQ:\r
329 Status = Pop (&Element1, VersionType);\r
330 if (EFI_ERROR (Status)) {\r
331 goto Error;\r
332 }\r
333 Status = Pop (&Element2, VersionType);\r
334 if (EFI_ERROR (Status)) {\r
335 goto Error;\r
336 }\r
337 Status = (Element1.Value.Version == Element2.Value.Version) ? Push (TRUE, BooleanType) : Push (FALSE, BooleanType);\r
338 if (EFI_ERROR (Status)) {\r
339 goto Error;\r
340 }\r
341 break;\r
342 case EFI_FMP_DEP_GT:\r
343 Status = Pop (&Element1, VersionType);\r
344 if (EFI_ERROR (Status)) {\r
345 goto Error;\r
346 }\r
347 Status = Pop (&Element2, VersionType);\r
348 if (EFI_ERROR (Status)) {\r
349 goto Error;\r
350 }\r
351 Status = (Element1.Value.Version > Element2.Value.Version) ? Push (TRUE, BooleanType) : Push (FALSE, BooleanType);\r
352 if (EFI_ERROR (Status)) {\r
353 goto Error;\r
354 }\r
355 break;\r
356 case EFI_FMP_DEP_GTE:\r
357 Status = Pop (&Element1, VersionType);\r
358 if (EFI_ERROR (Status)) {\r
359 goto Error;\r
360 }\r
361 Status = Pop (&Element2, VersionType);\r
362 if (EFI_ERROR (Status)) {\r
363 goto Error;\r
364 }\r
365 Status = (Element1.Value.Version >= Element2.Value.Version) ? Push (TRUE, BooleanType) : Push (FALSE, BooleanType);\r
366 if (EFI_ERROR (Status)) {\r
367 goto Error;\r
368 }\r
369 break;\r
370 case EFI_FMP_DEP_LT:\r
371 Status = Pop (&Element1, VersionType);\r
372 if (EFI_ERROR (Status)) {\r
373 goto Error;\r
374 }\r
375 Status = Pop (&Element2, VersionType);\r
376 if (EFI_ERROR (Status)) {\r
377 goto Error;\r
378 }\r
379 Status = (Element1.Value.Version < Element2.Value.Version) ? Push (TRUE, BooleanType) : Push (FALSE, BooleanType);\r
380 if (EFI_ERROR (Status)) {\r
381 goto Error;\r
382 }\r
383 break;\r
384 case EFI_FMP_DEP_LTE:\r
385 Status = Pop (&Element1, VersionType);\r
386 if (EFI_ERROR (Status)) {\r
387 goto Error;\r
388 }\r
389 Status = Pop (&Element2, VersionType);\r
390 if (EFI_ERROR (Status)) {\r
391 goto Error;\r
392 }\r
393 Status = (Element1.Value.Version <= Element2.Value.Version) ? Push (TRUE, BooleanType) : Push (FALSE, BooleanType);\r
394 if (EFI_ERROR (Status)) {\r
395 goto Error;\r
396 }\r
397 break;\r
398 case EFI_FMP_DEP_END:\r
399 Status = Pop (&Element1, BooleanType);\r
400 if (EFI_ERROR (Status)) {\r
401 goto Error;\r
402 }\r
403 return Element1.Value.Boolean;\r
404 default:\r
405 Status = EFI_INVALID_PARAMETER;\r
406 goto Error;\r
407 }\r
408 Iterator++;\r
409 }\r
410\r
411Error:\r
412\r
413 DEBUG ((DEBUG_ERROR, "FmpDxe(%s): EvaluateDependencies() - RESULT = FALSE (Status = %r)\n", mImageIdName, Status));\r
414 return FALSE;\r
415}\r
416\r
417/**\r
418 Validate the dependency expression and output its size.\r
419\r
420 @param[in] ImageDepex Pointer to the EFI_FIRMWARE_IMAGE_DEP.\r
421 @param[in] MaxDepexSize Max size of the dependency.\r
422 @param[out] DepexSize Size of dependency.\r
423\r
424 @retval TRUE The capsule is valid.\r
425 @retval FALSE The capsule is invalid.\r
426\r
427**/\r
428BOOLEAN\r
429ValidateImageDepex (\r
430 IN EFI_FIRMWARE_IMAGE_DEP *ImageDepex,\r
431 IN CONST UINTN MaxDepexSize,\r
432 OUT UINT32 *DepexSize\r
433 )\r
434{\r
435 UINT8 *Depex;\r
436\r
437 *DepexSize = 0;\r
438 Depex = ImageDepex->Dependencies;\r
439 while (Depex < ImageDepex->Dependencies + MaxDepexSize) {\r
440 switch (*Depex)\r
441 {\r
442 case EFI_FMP_DEP_PUSH_GUID:\r
443 Depex += sizeof (EFI_GUID) + 1;\r
444 break;\r
445 case EFI_FMP_DEP_PUSH_VERSION:\r
446 Depex += sizeof (UINT32) + 1;\r
447 break;\r
448 case EFI_FMP_DEP_VERSION_STR:\r
449 Depex += AsciiStrnLenS ((CHAR8 *) Depex, ImageDepex->Dependencies + MaxDepexSize - Depex) + 1;\r
450 break;\r
451 case EFI_FMP_DEP_AND:\r
452 case EFI_FMP_DEP_OR:\r
453 case EFI_FMP_DEP_NOT:\r
454 case EFI_FMP_DEP_TRUE:\r
455 case EFI_FMP_DEP_FALSE:\r
456 case EFI_FMP_DEP_EQ:\r
457 case EFI_FMP_DEP_GT:\r
458 case EFI_FMP_DEP_GTE:\r
459 case EFI_FMP_DEP_LT:\r
460 case EFI_FMP_DEP_LTE:\r
461 Depex += 1;\r
462 break;\r
463 case EFI_FMP_DEP_END:\r
464 Depex += 1;\r
465 *DepexSize = (UINT32)(Depex - ImageDepex->Dependencies);\r
466 return TRUE;\r
467 default:\r
468 return FALSE;\r
469 }\r
470 }\r
471\r
472 return FALSE;\r
473}\r
474\r
475\r
476/**\r
477 Get the size of dependencies. Assume the dependencies is validated before\r
478 calling this function.\r
479\r
480 @param[in] Dependencies Pointer to the EFI_FIRMWARE_IMAGE_DEP.\r
481\r
482 @retval The size of dependencies.\r
483\r
484**/\r
485UINTN\r
486GetDepexSize (\r
487 IN CONST EFI_FIRMWARE_IMAGE_DEP *Dependencies\r
488 )\r
489{\r
490 UINTN Index;\r
491\r
492 if (Dependencies == NULL) {\r
493 return 0;\r
494 }\r
495\r
496 Index = 0;\r
497 while (Dependencies->Dependencies[Index] != EFI_FMP_DEP_END) {\r
498 Index ++;\r
499 }\r
500\r
501 return Index + 1;\r
502}\r
503\r
504/**\r
505 Check dependency for firmware update.\r
506\r
507 @param[in] ImageTypeId Image Type Id.\r
508 @param[in] Version New version.\r
509 @param[in] Dependencies The dependencies.\r
510 @param[in] DependenciesSize Size of the dependencies\r
511 @param[out] IsSatisfied Indicate the dependencies is satisfied or not.\r
512\r
513 @retval EFI_SUCCESS Dependency Evaluation is successful.\r
514 @retval Others Dependency Evaluation fails with unexpected error.\r
515\r
516**/\r
517EFI_STATUS\r
518EvaluateImageDependencies (\r
519 IN CONST EFI_GUID ImageTypeId,\r
520 IN CONST UINT32 Version,\r
521 IN CONST EFI_FIRMWARE_IMAGE_DEP *Dependencies,\r
522 IN CONST UINT32 DependenciesSize,\r
523 OUT BOOLEAN *IsSatisfied\r
524 )\r
525{\r
526 EFI_STATUS Status;\r
527 EFI_HANDLE *HandleBuffer;\r
528 UINTN Index;\r
529 EFI_FIRMWARE_MANAGEMENT_PROTOCOL *Fmp;\r
530 UINTN ImageInfoSize;\r
531 UINT32 FmpImageInfoDescriptorVer;\r
532 UINT8 FmpImageInfoCount;\r
533 UINTN DescriptorSize;\r
534 UINT32 PackageVersion;\r
535 CHAR16 *PackageVersionName;\r
536 UINTN DepexSize;\r
537\r
538 *IsSatisfied = TRUE;\r
539 PackageVersionName = NULL;\r
540\r
541 //\r
542 // Get ImageDescriptors of all FMP instances, and archive them for depex evaluation.\r
543 //\r
544 Status = gBS->LocateHandleBuffer (\r
545 ByProtocol,\r
546 &gEfiFirmwareManagementProtocolGuid,\r
547 NULL,\r
548 &mNumberOfFmpInstance,\r
549 &HandleBuffer\r
550 );\r
551 if (EFI_ERROR (Status)) {\r
552 return EFI_ABORTED;\r
553 }\r
554\r
55d6e39f 555 mFmpImageInfoBuf = AllocateZeroPool (sizeof(EFI_FIRMWARE_IMAGE_DESCRIPTOR *) * mNumberOfFmpInstance);\r
2ed845b3
WX
556 if (mFmpImageInfoBuf == NULL) {\r
557 return EFI_OUT_OF_RESOURCES;\r
558 }\r
559\r
560 for (Index = 0; Index < mNumberOfFmpInstance; Index ++) {\r
561 Status = gBS->HandleProtocol (\r
562 HandleBuffer[Index],\r
563 &gEfiFirmwareManagementProtocolGuid,\r
564 (VOID **) &Fmp\r
565 );\r
566 if (EFI_ERROR(Status)) {\r
567 continue;\r
568 }\r
569\r
570 ImageInfoSize = 0;\r
571 Status = Fmp->GetImageInfo (\r
572 Fmp,\r
573 &ImageInfoSize,\r
574 NULL,\r
575 NULL,\r
576 NULL,\r
577 NULL,\r
578 NULL,\r
579 NULL\r
580 );\r
581 if (Status != EFI_BUFFER_TOO_SMALL) {\r
582 continue;\r
583 }\r
584\r
585 mFmpImageInfoBuf[Index] = AllocateZeroPool (ImageInfoSize);\r
586 if (mFmpImageInfoBuf[Index] == NULL) {\r
587 continue;\r
588 }\r
589\r
590 Status = Fmp->GetImageInfo (\r
591 Fmp,\r
592 &ImageInfoSize, // ImageInfoSize\r
593 mFmpImageInfoBuf[Index], // ImageInfo\r
594 &FmpImageInfoDescriptorVer, // DescriptorVersion\r
595 &FmpImageInfoCount, // DescriptorCount\r
596 &DescriptorSize, // DescriptorSize\r
597 &PackageVersion, // PackageVersion\r
598 &PackageVersionName // PackageVersionName\r
599 );\r
600 if (EFI_ERROR(Status)) {\r
601 FreePool (mFmpImageInfoBuf[Index]);\r
602 mFmpImageInfoBuf[Index] = NULL;\r
603 continue;\r
604 }\r
605\r
606 if (PackageVersionName != NULL) {\r
607 FreePool (PackageVersionName);\r
608 PackageVersionName = NULL;\r
609 }\r
610 }\r
611\r
612 //\r
613 // Step 1 - Evaluate firmware image's depex, against the version of other Fmp instances.\r
614 //\r
615 if (Dependencies != NULL) {\r
616 *IsSatisfied = EvaluateDependencies (Dependencies, DependenciesSize);\r
617 }\r
618\r
619 if (!*IsSatisfied) {\r
620 goto cleanup;\r
621 }\r
622\r
623 //\r
624 // Step 2 - Evaluate the depex of all other Fmp instances, against the new version in\r
625 // the firmware image.\r
626 //\r
627\r
628 //\r
629 // Update the new version to mFmpImageInfoBuf.\r
630 //\r
631 for (Index = 0; Index < mNumberOfFmpInstance; Index ++) {\r
632 if (mFmpImageInfoBuf[Index] != NULL) {\r
633 if (CompareGuid (&ImageTypeId, &mFmpImageInfoBuf[Index]->ImageTypeId)) {\r
634 mFmpImageInfoBuf[Index]->Version = Version;\r
635 break;\r
636 }\r
637 }\r
638 }\r
639\r
640 //\r
641 // Evaluate the Dependencies one by one.\r
642 //\r
643 for (Index = 0; Index < mNumberOfFmpInstance; Index ++) {\r
644 if (mFmpImageInfoBuf[Index] != NULL) {\r
645 //\r
646 // Skip the Fmp instance to be "SetImage".\r
647 //\r
648 if (CompareGuid (&ImageTypeId, &mFmpImageInfoBuf[Index]->ImageTypeId)) {\r
649 continue;\r
650 }\r
651 if ((mFmpImageInfoBuf[Index]->AttributesSupported & IMAGE_ATTRIBUTE_DEPENDENCY) &&\r
652 mFmpImageInfoBuf[Index]->Dependencies != NULL) {\r
653 //\r
654 // Get the size of depex.\r
655 // Assume that the dependencies in EFI_FIRMWARE_IMAGE_DESCRIPTOR is validated when PopulateDescriptor().\r
656 //\r
657 DepexSize = GetDepexSize (mFmpImageInfoBuf[Index]->Dependencies);\r
658 if (DepexSize > 0) {\r
659 *IsSatisfied = EvaluateDependencies (mFmpImageInfoBuf[Index]->Dependencies, DepexSize);\r
660 if (!*IsSatisfied) {\r
661 break;\r
662 }\r
663 }\r
664 }\r
665 }\r
666 }\r
667\r
668cleanup:\r
669 if (mFmpImageInfoBuf != NULL) {\r
670 for (Index = 0; Index < mNumberOfFmpInstance; Index ++) {\r
671 if (mFmpImageInfoBuf[Index] != NULL) {\r
672 FreePool (mFmpImageInfoBuf[Index]);\r
673 }\r
674 }\r
675 FreePool (mFmpImageInfoBuf);\r
676 }\r
677\r
678 return EFI_SUCCESS;\r
679}\r