]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/EsrtDxe/EsrtImpl.c
MdeModulePkg: Apply uncrustify changes
[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 } else if (Status == EFI_SUCCESS) {
135 //
136 // if exist, update Esrt cache repository
137 //
138 if (RepositorySize % sizeof (EFI_SYSTEM_RESOURCE_ENTRY) != 0) {
139 DEBUG ((DEBUG_ERROR, "Repository Corrupt. Need to rebuild Repository.\n"));
140 //
141 // Repository is corrupt. Clear Repository before insert new entry
142 //
143 Status = gRT->SetVariable (
144 VariableName,
145 &gEfiCallerIdGuid,
146 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
147 0,
148 EsrtRepository
149 );
150 FreePool (EsrtRepository);
151 RepositorySize = 0;
152 EsrtRepository = NULL;
153 }
154
155 //
156 // Check Repository size constraint
157 //
158 if ( ((Attribute == ESRT_FROM_FMP) && (RepositorySize >= PcdGet32 (PcdMaxFmpEsrtCacheNum) * sizeof (EFI_SYSTEM_RESOURCE_ENTRY)))
159 || ((Attribute == ESRT_FROM_NONFMP) && (RepositorySize >= PcdGet32 (PcdMaxNonFmpEsrtCacheNum) * sizeof (EFI_SYSTEM_RESOURCE_ENTRY))))
160 {
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
175 CopyMem ((UINT8 *)EsrtRepositoryNew + RepositorySize, Entry, sizeof (EFI_SYSTEM_RESOURCE_ENTRY));
176
177 Status = gRT->SetVariable (
178 VariableName,
179 &gEfiCallerIdGuid,
180 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
181 RepositorySize + sizeof (EFI_SYSTEM_RESOURCE_ENTRY),
182 EsrtRepositoryNew
183 );
184 }
185
186 EXIT:
187 if (EsrtRepository != NULL) {
188 FreePool (EsrtRepository);
189 }
190
191 if (EsrtRepositoryNew != NULL) {
192 FreePool (EsrtRepositoryNew);
193 }
194
195 return Status;
196 }
197
198 /**
199 Delete ESRT Entry from ESRT repository.
200
201 @param[in] FwClass FwClass of Esrt entry to delete
202 @param[in] Attribute Esrt from Esrt private protocol or FMP instance
203
204 @retval EFI_SUCCESS Insert all entries Successfully
205 @retval EFI_NOT_FOUND ESRT entry with FwClass doesn't exsit
206
207 **/
208 EFI_STATUS
209 DeleteEsrtEntry (
210 IN EFI_GUID *FwClass,
211 IN UINTN Attribute
212 )
213 {
214 EFI_STATUS Status;
215 CHAR16 *VariableName;
216 EFI_SYSTEM_RESOURCE_ENTRY *EsrtRepository;
217 UINTN RepositorySize;
218 UINTN Index;
219 UINTN EsrtNum;
220
221 EsrtRepository = NULL;
222
223 //
224 // Get Esrt index buffer
225 //
226 if (Attribute == ESRT_FROM_FMP) {
227 VariableName = EFI_ESRT_FMP_VARIABLE_NAME;
228 } else {
229 VariableName = EFI_ESRT_NONFMP_VARIABLE_NAME;
230 }
231
232 Status = GetVariable2 (
233 VariableName,
234 &gEfiCallerIdGuid,
235 (VOID **)&EsrtRepository,
236 &RepositorySize
237 );
238
239 if (EFI_ERROR (Status)) {
240 goto EXIT;
241 }
242
243 if (EsrtRepository == NULL) {
244 Status = EFI_OUT_OF_RESOURCES;
245 goto EXIT;
246 }
247
248 if ((RepositorySize % sizeof (EFI_SYSTEM_RESOURCE_ENTRY)) != 0) {
249 DEBUG ((DEBUG_ERROR, "Repository Corrupt. Need to rebuild Repository.\n"));
250 //
251 // Repository is corrupt. Clear Repository before insert new entry
252 //
253 Status = gRT->SetVariable (
254 VariableName,
255 &gEfiCallerIdGuid,
256 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
257 0,
258 EsrtRepository
259 );
260 goto EXIT;
261 }
262
263 Status = EFI_NOT_FOUND;
264 EsrtNum = RepositorySize/sizeof (EFI_SYSTEM_RESOURCE_ENTRY);
265 for (Index = 0; Index < EsrtNum; Index++) {
266 //
267 // Delete Esrt entry if it is found in repository
268 //
269 if (CompareGuid (FwClass, &EsrtRepository[Index].FwClass)) {
270 //
271 // If delete Esrt entry is not at the rail
272 //
273 if (Index < EsrtNum - 1) {
274 CopyMem (&EsrtRepository[Index], &EsrtRepository[Index + 1], (EsrtNum - Index - 1) * sizeof (EFI_SYSTEM_RESOURCE_ENTRY));
275 }
276
277 //
278 // Update New Repository
279 //
280 Status = gRT->SetVariable (
281 VariableName,
282 &gEfiCallerIdGuid,
283 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
284 (EsrtNum - 1) * sizeof (EFI_SYSTEM_RESOURCE_ENTRY),
285 EsrtRepository
286 );
287 break;
288 }
289 }
290
291 EXIT:
292 if (EsrtRepository != NULL) {
293 FreePool (EsrtRepository);
294 }
295
296 return Status;
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 CopyMem (&EsrtRepository[Index], Entry, sizeof (EFI_SYSTEM_RESOURCE_ENTRY));
373 //
374 // Update New Repository
375 //
376 Status = gRT->SetVariable (
377 VariableName,
378 &gEfiCallerIdGuid,
379 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
380 RepositorySize,
381 EsrtRepository
382 );
383 break;
384 }
385 }
386 }
387
388 EXIT:
389 if (EsrtRepository != NULL) {
390 FreePool (EsrtRepository);
391 }
392
393 return Status;
394 }
395
396 /**
397 Return if this FMP is a system FMP or a device FMP, based upon FmpImageInfo.
398
399 @param[in] FmpImageInfo A pointer to EFI_FIRMWARE_IMAGE_DESCRIPTOR
400
401 @return TRUE It is a system FMP.
402 @return FALSE It is a device FMP.
403 **/
404 BOOLEAN
405 IsSystemFmp (
406 IN EFI_FIRMWARE_IMAGE_DESCRIPTOR *FmpImageInfo
407 )
408 {
409 GUID *Guid;
410 UINTN Count;
411 UINTN Index;
412
413 Guid = PcdGetPtr (PcdSystemFmpCapsuleImageTypeIdGuid);
414 Count = PcdGetSize (PcdSystemFmpCapsuleImageTypeIdGuid)/sizeof (GUID);
415
416 for (Index = 0; Index < Count; Index++, Guid++) {
417 if (CompareGuid (&FmpImageInfo->ImageTypeId, Guid)) {
418 return TRUE;
419 }
420 }
421
422 return FALSE;
423 }
424
425 /**
426 Init one ESRT entry according to input FmpImageInfo (V1, V2, V3) .
427
428 @param[in, out] EsrtEntry Esrt entry to be Init
429 @param[in] FmpImageInfo FMP image info descriptor
430 @param[in] DescriptorVersion FMP Image info descriptor version
431
432 **/
433 VOID
434 SetEsrtEntryFromFmpInfo (
435 IN OUT EFI_SYSTEM_RESOURCE_ENTRY *EsrtEntry,
436 IN EFI_FIRMWARE_IMAGE_DESCRIPTOR *FmpImageInfo,
437 IN UINT32 DescriptorVersion
438 )
439 {
440 EsrtEntry->FwVersion = FmpImageInfo->Version;
441 EsrtEntry->FwClass = FmpImageInfo->ImageTypeId;
442 if (IsSystemFmp (FmpImageInfo)) {
443 EsrtEntry->FwType = ESRT_FW_TYPE_SYSTEMFIRMWARE;
444 } else {
445 EsrtEntry->FwType = ESRT_FW_TYPE_DEVICEFIRMWARE;
446 }
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 {
474 EsrtEntry->CapsuleFlags = PcdGet16 (PcdSystemRebootAfterCapsuleProcessFlag);
475 }
476 }