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