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