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