]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/EsrtDxe/EsrtImpl.c
MdeModulePkg: Clean up source files
[mirror_edk2.git] / MdeModulePkg / Universal / EsrtDxe / EsrtImpl.c
CommitLineData
acd32208
CZ
1/** @file\r
2 Esrt management implementation.\r
3\r
d1102dba 4Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>\r
acd32208
CZ
5This program and the accompanying materials\r
6are licensed and made available under the terms and conditions of the BSD License\r
7which accompanies this distribution. The full text of the license may be found at\r
8http://opensource.org/licenses/bsd-license.php\r
9\r
10THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12\r
13**/\r
14\r
15#include "EsrtImpl.h"\r
16\r
17/**\r
d1102dba 18 Find Esrt Entry stored in ESRT repository.\r
acd32208
CZ
19\r
20 @param[in] FwClass Firmware class guid in Esrt entry\r
21 @param[in] Attribute Esrt from Non FMP or FMP instance\r
22 @param[out] Entry Esrt entry returned\r
d1102dba 23\r
acd32208
CZ
24 @retval EFI_SUCCESS Successfully find an Esrt entry\r
25 @retval EF_NOT_FOUND No Esrt entry found\r
26\r
27**/\r
28EFI_STATUS\r
29GetEsrtEntry (\r
30 IN EFI_GUID *FwClass,\r
31 IN UINTN Attribute,\r
32 OUT EFI_SYSTEM_RESOURCE_ENTRY *Entry\r
33 )\r
34{\r
35 EFI_STATUS Status;\r
36 CHAR16 *VariableName;\r
37 EFI_SYSTEM_RESOURCE_ENTRY *EsrtRepository;\r
38 UINTN RepositorySize;\r
39 UINTN Index;\r
40 UINTN EsrtNum;\r
41\r
42 EsrtRepository = NULL;\r
43\r
44 //\r
45 // Get Esrt index buffer\r
46 //\r
47 if (Attribute == ESRT_FROM_FMP) {\r
48 VariableName = EFI_ESRT_FMP_VARIABLE_NAME;\r
49 } else {\r
50 VariableName = EFI_ESRT_NONFMP_VARIABLE_NAME;\r
51 }\r
d1102dba 52\r
acd32208
CZ
53 Status = GetVariable2 (\r
54 VariableName,\r
55 &gEfiCallerIdGuid,\r
56 (VOID **) &EsrtRepository,\r
57 &RepositorySize\r
58 );\r
59\r
60 if (EFI_ERROR(Status)) {\r
61 goto EXIT;\r
62 }\r
63\r
64 if (RepositorySize % sizeof(EFI_SYSTEM_RESOURCE_ENTRY) != 0) {\r
65 DEBUG((EFI_D_ERROR, "Repository Corrupt. Need to rebuild Repository.\n"));\r
66 Status = EFI_ABORTED;\r
67 goto EXIT;\r
68 }\r
69\r
70 Status = EFI_NOT_FOUND;\r
71 EsrtNum = RepositorySize/sizeof(EFI_SYSTEM_RESOURCE_ENTRY);\r
72 for (Index = 0; Index < EsrtNum; Index++) {\r
73 if (CompareGuid(FwClass, &EsrtRepository[Index].FwClass)) {\r
74 CopyMem(Entry, &EsrtRepository[Index], sizeof(EFI_SYSTEM_RESOURCE_ENTRY));\r
75 Status = EFI_SUCCESS;\r
76 break;\r
77 }\r
78 }\r
79\r
80EXIT:\r
81 if (EsrtRepository != NULL) {\r
82 FreePool(EsrtRepository);\r
83 }\r
84\r
85 return Status;\r
86}\r
87\r
88/**\r
89 Insert a new ESRT entry into ESRT Cache repository.\r
90\r
91 @param[in] Entry Esrt entry to be set\r
92 @param[in] Attribute Esrt from Esrt private protocol or FMP instance\r
d1102dba 93\r
acd32208
CZ
94 @retval EFI_SUCCESS Successfully set a variable.\r
95\r
96**/\r
97EFI_STATUS\r
98InsertEsrtEntry(\r
99 IN EFI_SYSTEM_RESOURCE_ENTRY *Entry,\r
100 UINTN Attribute\r
101 )\r
102{\r
103 EFI_STATUS Status;\r
104 CHAR16 *VariableName;\r
105 EFI_SYSTEM_RESOURCE_ENTRY *EsrtRepository;\r
106 UINTN RepositorySize;\r
107 EFI_SYSTEM_RESOURCE_ENTRY *EsrtRepositoryNew;\r
108\r
109 EsrtRepository = NULL;\r
110 EsrtRepositoryNew = NULL;\r
111\r
112 //\r
113 // Get Esrt index buffer\r
114 //\r
115 if (Attribute == ESRT_FROM_FMP) {\r
116 VariableName = EFI_ESRT_FMP_VARIABLE_NAME;\r
117 } else {\r
118 VariableName = EFI_ESRT_NONFMP_VARIABLE_NAME;\r
119 }\r
120\r
121 Status = GetVariable2 (\r
122 VariableName,\r
123 &gEfiCallerIdGuid,\r
124 (VOID **) &EsrtRepository,\r
125 &RepositorySize\r
126 );\r
127\r
128 if (Status == EFI_NOT_FOUND) {\r
129 //\r
130 // If not exist, create new Esrt cache repository\r
131 //\r
132 Status = gRT->SetVariable(\r
133 VariableName,\r
134 &gEfiCallerIdGuid,\r
135 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,\r
136 sizeof(EFI_SYSTEM_RESOURCE_ENTRY),\r
137 Entry\r
138 );\r
139 return Status;\r
140\r
141 } else if (Status == EFI_SUCCESS) {\r
142 //\r
143 // if exist, update Esrt cache repository\r
144 //\r
145 if (RepositorySize % sizeof(EFI_SYSTEM_RESOURCE_ENTRY) != 0) {\r
146 DEBUG((EFI_D_ERROR, "Repository Corrupt. Need to rebuild Repository.\n"));\r
147 //\r
148 // Repository is corrupt. Clear Repository before insert new entry\r
149 //\r
150 Status = gRT->SetVariable(\r
151 VariableName,\r
152 &gEfiCallerIdGuid,\r
153 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,\r
154 0,\r
155 EsrtRepository\r
156 );\r
157 FreePool(EsrtRepository);\r
158 RepositorySize = 0;\r
159 EsrtRepository = NULL;\r
160 }\r
161\r
162 //\r
163 // Check Repository size constraint\r
164 //\r
165 if ((Attribute == ESRT_FROM_FMP && RepositorySize >= PcdGet32(PcdMaxFmpEsrtCacheNum) * sizeof(EFI_SYSTEM_RESOURCE_ENTRY))\r
166 ||(Attribute == ESRT_FROM_NONFMP && RepositorySize >= PcdGet32(PcdMaxNonFmpEsrtCacheNum) * sizeof(EFI_SYSTEM_RESOURCE_ENTRY)) ) {\r
167 Status = EFI_OUT_OF_RESOURCES;\r
168 goto EXIT;\r
169 }\r
170\r
171 EsrtRepositoryNew = AllocatePool(RepositorySize + sizeof(EFI_SYSTEM_RESOURCE_ENTRY));\r
172 if (EsrtRepositoryNew == NULL) {\r
173 Status = EFI_OUT_OF_RESOURCES;\r
174 goto EXIT;\r
175 }\r
176\r
a3ac2587 177 if (RepositorySize != 0 && EsrtRepository != NULL) {\r
acd32208
CZ
178 CopyMem(EsrtRepositoryNew, EsrtRepository, RepositorySize);\r
179 }\r
180 CopyMem((UINT8 *)EsrtRepositoryNew + RepositorySize, Entry, sizeof(EFI_SYSTEM_RESOURCE_ENTRY));\r
181\r
182 Status = gRT->SetVariable(\r
183 VariableName,\r
184 &gEfiCallerIdGuid,\r
185 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,\r
186 RepositorySize + sizeof(EFI_SYSTEM_RESOURCE_ENTRY),\r
187 EsrtRepositoryNew\r
188 );\r
189 }\r
190\r
191EXIT:\r
192 if (EsrtRepository != NULL) {\r
193 FreePool(EsrtRepository);\r
194 }\r
195\r
196 if (EsrtRepositoryNew != NULL) {\r
197 FreePool(EsrtRepositoryNew);\r
198 }\r
199\r
200 return Status;\r
201}\r
202\r
203/**\r
d1102dba 204 Delete ESRT Entry from ESRT repository.\r
acd32208 205\r
d1102dba 206 @param[in] FwClass FwClass of Esrt entry to delete\r
acd32208 207 @param[in] Attribute Esrt from Esrt private protocol or FMP instance\r
d1102dba
LG
208\r
209 @retval EFI_SUCCESS Insert all entries Successfully\r
acd32208 210 @retval EFI_NOT_FOUND ESRT entry with FwClass doesn't exsit\r
d1102dba 211\r
acd32208
CZ
212**/\r
213EFI_STATUS\r
214DeleteEsrtEntry(\r
215 IN EFI_GUID *FwClass,\r
216 IN UINTN Attribute\r
217 )\r
d1102dba 218{\r
acd32208
CZ
219 EFI_STATUS Status;\r
220 CHAR16 *VariableName;\r
221 EFI_SYSTEM_RESOURCE_ENTRY *EsrtRepository;\r
222 UINTN RepositorySize;\r
223 UINTN Index;\r
224 UINTN EsrtNum;\r
225\r
226 EsrtRepository = NULL;\r
d1102dba 227\r
acd32208
CZ
228 //\r
229 // Get Esrt index buffer\r
230 //\r
231 if (Attribute == ESRT_FROM_FMP) {\r
232 VariableName = EFI_ESRT_FMP_VARIABLE_NAME;\r
233 } else {\r
234 VariableName = EFI_ESRT_NONFMP_VARIABLE_NAME;\r
235 }\r
d1102dba 236\r
acd32208
CZ
237 Status = GetVariable2 (\r
238 VariableName,\r
239 &gEfiCallerIdGuid,\r
240 (VOID **) &EsrtRepository,\r
241 &RepositorySize\r
242 );\r
243\r
244 if (EFI_ERROR(Status)) {\r
245 goto EXIT;\r
246 }\r
247\r
248 if ((RepositorySize % sizeof(EFI_SYSTEM_RESOURCE_ENTRY)) != 0) {\r
249 DEBUG((EFI_D_ERROR, "Repository Corrupt. Need to rebuild Repository.\n"));\r
250 //\r
251 // Repository is corrupt. Clear Repository before insert new entry\r
252 //\r
253 Status = gRT->SetVariable(\r
254 VariableName,\r
255 &gEfiCallerIdGuid,\r
256 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,\r
257 0,\r
258 EsrtRepository\r
259 );\r
260 goto EXIT;\r
261 }\r
262\r
263 Status = EFI_NOT_FOUND;\r
264 EsrtNum = RepositorySize/sizeof(EFI_SYSTEM_RESOURCE_ENTRY);\r
265 for (Index = 0; Index < EsrtNum; Index++) {\r
266 //\r
267 // Delete Esrt entry if it is found in repository\r
268 //\r
269 if (CompareGuid(FwClass, &EsrtRepository[Index].FwClass)) {\r
270 //\r
271 // If delete Esrt entry is not at the rail\r
272 //\r
273 if (Index < EsrtNum - 1) {\r
274 CopyMem(&EsrtRepository[Index], &EsrtRepository[Index + 1], (EsrtNum - Index - 1) * sizeof(EFI_SYSTEM_RESOURCE_ENTRY));\r
275 }\r
276\r
277 //\r
278 // Update New Repository\r
279 //\r
280 Status = gRT->SetVariable(\r
281 VariableName,\r
282 &gEfiCallerIdGuid,\r
283 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,\r
284 (EsrtNum - 1) * sizeof(EFI_SYSTEM_RESOURCE_ENTRY),\r
285 EsrtRepository\r
286 );\r
287 break;\r
288 }\r
289 }\r
290\r
291EXIT:\r
292 if (EsrtRepository != NULL) {\r
293 FreePool(EsrtRepository);\r
294 }\r
295\r
296 return Status;\r
297\r
298}\r
299\r
300/**\r
301 Update one ESRT entry in ESRT repository\r
302\r
303 @param[in] Entry Esrt entry to be set\r
304 @param[in] Attribute Esrt from Non Esrt or FMP instance\r
d1102dba 305\r
acd32208
CZ
306 @retval EFI_SUCCESS Successfully Update a variable.\r
307 @retval EFI_NOT_FOUND The Esrt enry doesn't exist\r
308\r
309**/\r
310EFI_STATUS\r
311UpdateEsrtEntry(\r
312 IN EFI_SYSTEM_RESOURCE_ENTRY *Entry,\r
313 UINTN Attribute\r
314 )\r
315{\r
316 EFI_STATUS Status;\r
317 CHAR16 *VariableName;\r
318 EFI_SYSTEM_RESOURCE_ENTRY *EsrtRepository;\r
319 UINTN RepositorySize;\r
320 UINTN Index;\r
321 UINTN EsrtNum;\r
322\r
323 EsrtRepository = NULL;\r
324\r
325 //\r
326 // Get Esrt index buffer\r
327 //\r
328 if (Attribute == ESRT_FROM_FMP) {\r
329 VariableName = EFI_ESRT_FMP_VARIABLE_NAME;\r
330 } else {\r
331 VariableName = EFI_ESRT_NONFMP_VARIABLE_NAME;\r
332 }\r
333\r
334 Status = GetVariable2 (\r
335 VariableName,\r
336 &gEfiCallerIdGuid,\r
337 (VOID **) &EsrtRepository,\r
338 &RepositorySize\r
339 );\r
340\r
341 if (!EFI_ERROR(Status)) {\r
342 //\r
343 // if exist, update Esrt cache repository\r
344 //\r
345 if (RepositorySize % sizeof(EFI_SYSTEM_RESOURCE_ENTRY) != 0) {\r
346 DEBUG((EFI_D_ERROR, "Repository Corrupt. Need to rebuild Repository.\n"));\r
347 //\r
348 // Repository is corrupt. Clear Repository before insert new entry\r
349 //\r
350 Status = gRT->SetVariable(\r
351 VariableName,\r
352 &gEfiCallerIdGuid,\r
353 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,\r
354 0,\r
355 EsrtRepository\r
356 );\r
357 Status = EFI_NOT_FOUND;\r
358 goto EXIT;\r
359 }\r
360\r
361 Status = EFI_NOT_FOUND;\r
362 EsrtNum = RepositorySize/sizeof(EFI_SYSTEM_RESOURCE_ENTRY);\r
363 for (Index = 0; Index < EsrtNum; Index++) {\r
364 //\r
365 // Update Esrt entry if it is found in repository\r
366 //\r
367 if (CompareGuid(&Entry->FwClass, &EsrtRepository[Index].FwClass)) {\r
368\r
369 CopyMem(&EsrtRepository[Index], Entry, sizeof(EFI_SYSTEM_RESOURCE_ENTRY));\r
370 //\r
371 // Update New Repository\r
372 //\r
373 Status = gRT->SetVariable(\r
374 VariableName,\r
375 &gEfiCallerIdGuid,\r
376 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,\r
377 RepositorySize,\r
378 EsrtRepository\r
379 );\r
380 break;\r
381 }\r
382 }\r
383 }\r
384\r
385EXIT:\r
386 if (EsrtRepository != NULL) {\r
387 FreePool(EsrtRepository);\r
388 }\r
389\r
390 return Status;\r
391}\r
392\r
ab3aac14
JY
393/**\r
394 Return if this FMP is a system FMP or a device FMP, based upon FmpImageInfo.\r
395\r
396 @param[in] FmpImageInfo A pointer to EFI_FIRMWARE_IMAGE_DESCRIPTOR\r
397\r
398 @return TRUE It is a system FMP.\r
399 @return FALSE It is a device FMP.\r
400**/\r
401BOOLEAN\r
402IsSystemFmp (\r
403 IN EFI_FIRMWARE_IMAGE_DESCRIPTOR *FmpImageInfo\r
404 )\r
405{\r
406 GUID *Guid;\r
407 UINTN Count;\r
408 UINTN Index;\r
409\r
410 Guid = PcdGetPtr(PcdSystemFmpCapsuleImageTypeIdGuid);\r
411 Count = PcdGetSize(PcdSystemFmpCapsuleImageTypeIdGuid)/sizeof(GUID);\r
412\r
413 for (Index = 0; Index < Count; Index++, Guid++) {\r
414 if (CompareGuid(&FmpImageInfo->ImageTypeId, Guid)) {\r
415 return TRUE;\r
416 }\r
417 }\r
418\r
419 return FALSE;\r
420}\r
421\r
acd32208
CZ
422/**\r
423 Init one ESRT entry according to input FmpImageInfo (V1, V2, V3) .\r
424\r
a3ac2587
CZ
425 @param[in, out] EsrtEntry Esrt entry to be Init\r
426 @param[in] FmpImageInfo FMP image info descriptor\r
427 @param[in] DescriptorVersion FMP Image info descriptor version\r
d1102dba 428\r
acd32208 429**/\r
d1102dba 430VOID\r
acd32208
CZ
431SetEsrtEntryFromFmpInfo (\r
432 IN OUT EFI_SYSTEM_RESOURCE_ENTRY *EsrtEntry,\r
433 IN EFI_FIRMWARE_IMAGE_DESCRIPTOR *FmpImageInfo,\r
434 IN UINT32 DescriptorVersion\r
435 )\r
436{\r
437 EsrtEntry->FwVersion = FmpImageInfo->Version;\r
438 EsrtEntry->FwClass = FmpImageInfo->ImageTypeId;\r
ab3aac14
JY
439 if (IsSystemFmp(FmpImageInfo)) {\r
440 EsrtEntry->FwType = ESRT_FW_TYPE_SYSTEMFIRMWARE;\r
441 } else {\r
442 EsrtEntry->FwType = ESRT_FW_TYPE_DEVICEFIRMWARE;\r
443 }\r
acd32208
CZ
444 EsrtEntry->LowestSupportedFwVersion = 0;\r
445 EsrtEntry->CapsuleFlags = 0;\r
446 EsrtEntry->LastAttemptVersion = 0;\r
447 EsrtEntry->LastAttemptStatus = LAST_ATTEMPT_STATUS_SUCCESS;\r
448\r
449 if (DescriptorVersion >= 2) {\r
450 //\r
451 // LowestSupportedImageVersion only available in FMP V2 or higher\r
452 //\r
453 EsrtEntry->LowestSupportedFwVersion = FmpImageInfo->LowestSupportedImageVersion;\r
d1102dba 454 }\r
acd32208
CZ
455\r
456 if (DescriptorVersion >= 3) {\r
457 //\r
458 // LastAttemptVersion & LastAttemptStatus only available in FMP V3 or higher\r
459 //\r
460 EsrtEntry->LastAttemptVersion = FmpImageInfo->LastAttemptVersion;\r
461 EsrtEntry->LastAttemptStatus = FmpImageInfo->LastAttemptStatus;\r
d1102dba 462 }\r
acd32208
CZ
463\r
464 //\r
465 // Set capsule customized flag\r
466 //\r
467 if ((FmpImageInfo->AttributesSupported & IMAGE_ATTRIBUTE_RESET_REQUIRED) != 0\r
468 && (FmpImageInfo->AttributesSetting & IMAGE_ATTRIBUTE_RESET_REQUIRED) != 0) {\r
469 EsrtEntry->CapsuleFlags = PcdGet16(PcdSystemRebootAfterCapsuleProcessFlag);\r
470 }\r
471}\r