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