]> git.proxmox.com Git - mirror_edk2.git/blame - FmpDevicePkg/Library/FmpDependencyCheckLib/FmpDependencyCheckLib.c
FmpDevicePkg/FmpDependencyCheckLib: Return unsatisfied on handle failure
[mirror_edk2.git] / FmpDevicePkg / Library / FmpDependencyCheckLib / FmpDependencyCheckLib.c
CommitLineData
6c496642
WX
1/** @file\r
2 Provides FMP capsule dependency check services when updating the firmware\r
3 image of a FMP device.\r
4\r
e4e27351 5 Copyright (c) Microsoft Corporation.<BR>\r
6c496642
WX
6 Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>\r
7\r
8 SPDX-License-Identifier: BSD-2-Clause-Patent\r
9\r
10**/\r
11#include <PiDxe.h>\r
12#include <Library/BaseLib.h>\r
13#include <Library/BaseMemoryLib.h>\r
14#include <Library/DebugLib.h>\r
15#include <Library/FmpDependencyLib.h>\r
16#include <Library/FmpDependencyCheckLib.h>\r
17#include <Library/MemoryAllocationLib.h>\r
18#include <Library/UefiLib.h>\r
19#include <Library/UefiBootServicesTableLib.h>\r
20\r
21/**\r
22 Check dependency for firmware update.\r
23\r
24 @param[in] ImageTypeId Image Type Id.\r
25 @param[in] Version New version.\r
26 @param[in] Dependencies Fmp dependency.\r
27 @param[in] DependenciesSize Size, in bytes, of the Fmp dependency.\r
28\r
29 @retval TRUE Dependencies are satisfied.\r
30 @retval FALSE Dependencies are unsatisfied or dependency check fails.\r
31\r
32**/\r
33BOOLEAN\r
34EFIAPI\r
35CheckFmpDependency (\r
36 IN EFI_GUID ImageTypeId,\r
37 IN UINT32 Version,\r
38 IN EFI_FIRMWARE_IMAGE_DEP *Dependencies, OPTIONAL\r
39 IN UINT32 DependenciesSize\r
40 )\r
41{\r
42 EFI_STATUS Status;\r
43 EFI_HANDLE *HandleBuffer;\r
44 UINTN Index;\r
45 EFI_FIRMWARE_MANAGEMENT_PROTOCOL *Fmp;\r
46 UINTN ImageInfoSize;\r
47 UINT32 *DescriptorVer;\r
48 UINT8 FmpImageInfoCount;\r
49 UINTN *DescriptorSize;\r
50 UINT32 PackageVersion;\r
51 CHAR16 *PackageVersionName;\r
52 UINTN NumberOfFmpInstance;\r
53 EFI_FIRMWARE_IMAGE_DESCRIPTOR **FmpImageInfoBuf;\r
54 FMP_DEPEX_CHECK_VERSION_DATA *FmpVersions;\r
55 UINTN FmpVersionsCount;\r
56 BOOLEAN IsSatisfied;\r
57\r
58 FmpImageInfoBuf = NULL;\r
59 DescriptorVer = NULL;\r
60 DescriptorSize = NULL;\r
61 NumberOfFmpInstance = 0;\r
62 FmpVersions = NULL;\r
63 FmpVersionsCount = 0;\r
64 IsSatisfied = TRUE;\r
65 PackageVersionName = NULL;\r
66\r
67 //\r
68 // Get ImageDescriptors of all FMP instances, and archive them for dependency evaluation.\r
69 //\r
70 Status = gBS->LocateHandleBuffer (\r
71 ByProtocol,\r
72 &gEfiFirmwareManagementProtocolGuid,\r
73 NULL,\r
74 &NumberOfFmpInstance,\r
75 &HandleBuffer\r
76 );\r
77 if (EFI_ERROR (Status)) {\r
78 DEBUG ((DEBUG_ERROR, "CheckFmpDependency: Get Firmware Management Protocol failed. (%r)", Status));\r
e4e27351 79 IsSatisfied = FALSE;\r
6c496642
WX
80 goto cleanup;\r
81 }\r
82\r
83 FmpImageInfoBuf = AllocateZeroPool (sizeof(EFI_FIRMWARE_IMAGE_DESCRIPTOR *) * NumberOfFmpInstance);\r
84 if (FmpImageInfoBuf == NULL) {\r
85 IsSatisfied = FALSE;\r
86 goto cleanup;\r
87 }\r
88\r
89 DescriptorVer = AllocateZeroPool (sizeof(UINT32) * NumberOfFmpInstance);\r
90 if (DescriptorVer == NULL ) {\r
91 IsSatisfied = FALSE;\r
92 goto cleanup;\r
93 }\r
94\r
95 DescriptorSize = AllocateZeroPool (sizeof(UINTN) * NumberOfFmpInstance);\r
96 if (DescriptorSize == NULL ) {\r
97 IsSatisfied = FALSE;\r
98 goto cleanup;\r
99 }\r
100\r
101 FmpVersions = AllocateZeroPool (sizeof(FMP_DEPEX_CHECK_VERSION_DATA) * NumberOfFmpInstance);\r
102 if (FmpVersions == NULL) {\r
103 IsSatisfied = FALSE;\r
104 goto cleanup;\r
105 }\r
106\r
107 for (Index = 0; Index < NumberOfFmpInstance; Index ++) {\r
108 Status = gBS->HandleProtocol (\r
109 HandleBuffer[Index],\r
110 &gEfiFirmwareManagementProtocolGuid,\r
111 (VOID **) &Fmp\r
112 );\r
113 if (EFI_ERROR(Status)) {\r
114 continue;\r
115 }\r
116\r
117 ImageInfoSize = 0;\r
118 Status = Fmp->GetImageInfo (\r
119 Fmp,\r
120 &ImageInfoSize,\r
121 NULL,\r
122 NULL,\r
123 NULL,\r
124 NULL,\r
125 NULL,\r
126 NULL\r
127 );\r
128 if (Status != EFI_BUFFER_TOO_SMALL) {\r
129 continue;\r
130 }\r
131\r
132 FmpImageInfoBuf[Index] = AllocateZeroPool (ImageInfoSize);\r
133 if (FmpImageInfoBuf[Index] == NULL) {\r
134 continue;\r
135 }\r
136\r
137 Status = Fmp->GetImageInfo (\r
138 Fmp,\r
139 &ImageInfoSize, // ImageInfoSize\r
140 FmpImageInfoBuf[Index], // ImageInfo\r
141 &DescriptorVer[Index], // DescriptorVersion\r
142 &FmpImageInfoCount, // DescriptorCount\r
143 &DescriptorSize[Index], // DescriptorSize\r
144 &PackageVersion, // PackageVersion\r
145 &PackageVersionName // PackageVersionName\r
146 );\r
147 if (EFI_ERROR(Status)) {\r
148 FreePool (FmpImageInfoBuf[Index]);\r
149 FmpImageInfoBuf[Index] = NULL;\r
150 continue;\r
151 }\r
152\r
153 if (PackageVersionName != NULL) {\r
154 FreePool (PackageVersionName);\r
155 PackageVersionName = NULL;\r
156 }\r
157\r
158 CopyGuid (&FmpVersions[FmpVersionsCount].ImageTypeId, &FmpImageInfoBuf[Index]->ImageTypeId);\r
159 FmpVersions[FmpVersionsCount].Version = FmpImageInfoBuf[Index]->Version;\r
160 FmpVersionsCount ++;\r
161 }\r
162\r
163 //\r
164 // Evaluate firmware image's depex, against the version of other Fmp instances.\r
165 //\r
166 if (Dependencies != NULL) {\r
167 IsSatisfied = EvaluateDependency (Dependencies, DependenciesSize, FmpVersions, FmpVersionsCount);\r
168 }\r
169\r
170 if (!IsSatisfied) {\r
171 DEBUG ((DEBUG_ERROR, "CheckFmpDependency: %g\'s dependency is not satisfied!\n", ImageTypeId));\r
172 goto cleanup;\r
173 }\r
174\r
175cleanup:\r
176 if (FmpImageInfoBuf != NULL) {\r
177 for (Index = 0; Index < NumberOfFmpInstance; Index ++) {\r
178 if (FmpImageInfoBuf[Index] != NULL) {\r
179 FreePool (FmpImageInfoBuf[Index]);\r
180 }\r
181 }\r
182 FreePool (FmpImageInfoBuf);\r
183 }\r
184\r
185 if (DescriptorVer != NULL) {\r
186 FreePool (DescriptorVer);\r
187 }\r
188\r
189 if (DescriptorSize != NULL) {\r
190 FreePool (DescriptorSize);\r
191 }\r
192\r
193 if (FmpVersions != NULL) {\r
194 FreePool (FmpVersions);\r
195 }\r
196\r
197 return IsSatisfied;\r
198}\r