VirtualBox

source: vbox/trunk/src/VBox/Devices/EFI/FirmwareNew/MdeModulePkg/Universal/EsrtDxe/EsrtImpl.c@ 77662

最後變更 在這個檔案從77662是 77662,由 vboxsync 提交於 6 年 前

EFI: First step in UDK2018 merge. Does not build yet.

  • 屬性 svn:eol-style 設為 native
檔案大小: 13.1 KB
 
1/** @file
2 Esrt management implementation.
3
4Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved.<BR>
5This program and the accompanying materials
6are licensed and made available under the terms and conditions of the BSD License
7which accompanies this distribution. The full text of the license may be found at
8http://opensource.org/licenses/bsd-license.php
9
10THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11WITHOUT 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**/
28EFI_STATUS
29GetEsrtEntry (
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
80EXIT:
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**/
97EFI_STATUS
98InsertEsrtEntry(
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
191EXIT:
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**/
213EFI_STATUS
214DeleteEsrtEntry(
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
291EXIT:
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**/
310EFI_STATUS
311UpdateEsrtEntry(
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
385EXIT:
386 if (EsrtRepository != NULL) {
387 FreePool(EsrtRepository);
388 }
389
390 return Status;
391}
392
393/**
394 Return if this FMP is a system FMP or a device FMP, based upon FmpImageInfo.
395
396 @param[in] FmpImageInfo A pointer to EFI_FIRMWARE_IMAGE_DESCRIPTOR
397
398 @return TRUE It is a system FMP.
399 @return FALSE It is a device FMP.
400**/
401BOOLEAN
402IsSystemFmp (
403 IN EFI_FIRMWARE_IMAGE_DESCRIPTOR *FmpImageInfo
404 )
405{
406 GUID *Guid;
407 UINTN Count;
408 UINTN Index;
409
410 Guid = PcdGetPtr(PcdSystemFmpCapsuleImageTypeIdGuid);
411 Count = PcdGetSize(PcdSystemFmpCapsuleImageTypeIdGuid)/sizeof(GUID);
412
413 for (Index = 0; Index < Count; Index++, Guid++) {
414 if (CompareGuid(&FmpImageInfo->ImageTypeId, Guid)) {
415 return TRUE;
416 }
417 }
418
419 return FALSE;
420}
421
422/**
423 Init one ESRT entry according to input FmpImageInfo (V1, V2, V3) .
424
425 @param[in, out] EsrtEntry Esrt entry to be Init
426 @param[in] FmpImageInfo FMP image info descriptor
427 @param[in] DescriptorVersion FMP Image info descriptor version
428
429**/
430VOID
431SetEsrtEntryFromFmpInfo (
432 IN OUT EFI_SYSTEM_RESOURCE_ENTRY *EsrtEntry,
433 IN EFI_FIRMWARE_IMAGE_DESCRIPTOR *FmpImageInfo,
434 IN UINT32 DescriptorVersion
435 )
436{
437 EsrtEntry->FwVersion = FmpImageInfo->Version;
438 EsrtEntry->FwClass = FmpImageInfo->ImageTypeId;
439 if (IsSystemFmp(FmpImageInfo)) {
440 EsrtEntry->FwType = ESRT_FW_TYPE_SYSTEMFIRMWARE;
441 } else {
442 EsrtEntry->FwType = ESRT_FW_TYPE_DEVICEFIRMWARE;
443 }
444 EsrtEntry->LowestSupportedFwVersion = 0;
445 EsrtEntry->CapsuleFlags = 0;
446 EsrtEntry->LastAttemptVersion = 0;
447 EsrtEntry->LastAttemptStatus = LAST_ATTEMPT_STATUS_SUCCESS;
448
449 if (DescriptorVersion >= 2) {
450 //
451 // LowestSupportedImageVersion only available in FMP V2 or higher
452 //
453 EsrtEntry->LowestSupportedFwVersion = FmpImageInfo->LowestSupportedImageVersion;
454 }
455
456 if (DescriptorVersion >= 3) {
457 //
458 // LastAttemptVersion & LastAttemptStatus only available in FMP V3 or higher
459 //
460 EsrtEntry->LastAttemptVersion = FmpImageInfo->LastAttemptVersion;
461 EsrtEntry->LastAttemptStatus = FmpImageInfo->LastAttemptStatus;
462 }
463
464 //
465 // Set capsule customized flag
466 //
467 if ((FmpImageInfo->AttributesSupported & IMAGE_ATTRIBUTE_RESET_REQUIRED) != 0
468 && (FmpImageInfo->AttributesSetting & IMAGE_ATTRIBUTE_RESET_REQUIRED) != 0) {
469 EsrtEntry->CapsuleFlags = PcdGet16(PcdSystemRebootAfterCapsuleProcessFlag);
470 }
471}
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette