TianoCore EDK2 master
Loading...
Searching...
No Matches
EsrtDxe.c
Go to the documentation of this file.
1
8#include "EsrtImpl.h"
9
10//
11// Module globals.
12//
13
14ESRT_PRIVATE_DATA mPrivate;
15
16ESRT_MANAGEMENT_PROTOCOL mEsrtManagementProtocolTemplate = {
23};
24
37EFIAPI
39 IN EFI_GUID *FwClass,
41 )
42{
43 EFI_STATUS Status;
44
45 if ((FwClass == NULL) || (Entry == NULL)) {
46 return EFI_INVALID_PARAMETER;
47 }
48
49 Status = EfiAcquireLockOrFail (&mPrivate.NonFmpLock);
50 if (EFI_ERROR (Status)) {
51 return Status;
52 }
53
54 //
55 // Find in Non-FMP Cached Esrt Repository
56 //
57 Status = GetEsrtEntry (
58 FwClass,
59 ESRT_FROM_NONFMP,
60 Entry
61 );
62
63 EfiReleaseLock (&mPrivate.NonFmpLock);
64
65 if (EFI_ERROR (Status)) {
66 Status = EfiAcquireLockOrFail (&mPrivate.FmpLock);
67 if (EFI_ERROR (Status)) {
68 return Status;
69 }
70
71 //
72 // Find in FMP Cached Esrt NV Variable
73 //
74 Status = GetEsrtEntry (
75 FwClass,
76 ESRT_FROM_FMP,
77 Entry
78 );
79
80 EfiReleaseLock (&mPrivate.FmpLock);
81 }
82
83 return Status;
84}
85
97EFIAPI
100 )
101{
102 EFI_STATUS Status;
103
104 if (Entry == NULL) {
105 return EFI_INVALID_PARAMETER;
106 }
107
108 Status = EfiAcquireLockOrFail (&mPrivate.FmpLock);
109 if (EFI_ERROR (Status)) {
110 return Status;
111 }
112
113 Status = UpdateEsrtEntry (Entry, ESRT_FROM_FMP);
114
115 if (!EFI_ERROR (Status)) {
116 EfiReleaseLock (&mPrivate.FmpLock);
117 return Status;
118 }
119
120 EfiReleaseLock (&mPrivate.FmpLock);
121
122 Status = EfiAcquireLockOrFail (&mPrivate.NonFmpLock);
123 if (EFI_ERROR (Status)) {
124 return Status;
125 }
126
127 Status = UpdateEsrtEntry (Entry, ESRT_FROM_NONFMP);
128
129 EfiReleaseLock (&mPrivate.NonFmpLock);
130
131 return Status;
132}
133
144EFIAPI
146 IN EFI_GUID *FwClass
147 )
148{
149 EFI_STATUS Status;
150
151 if (FwClass == NULL) {
152 return EFI_INVALID_PARAMETER;
153 }
154
155 Status = EfiAcquireLockOrFail (&mPrivate.NonFmpLock);
156 if (EFI_ERROR (Status)) {
157 return Status;
158 }
159
160 Status = DeleteEsrtEntry (FwClass, ESRT_FROM_NONFMP);
161
162 EfiReleaseLock (&mPrivate.NonFmpLock);
163
164 return Status;
165}
166
178EFIAPI
181 )
182{
183 EFI_STATUS Status;
184 EFI_SYSTEM_RESOURCE_ENTRY EsrtEntryTmp;
185
186 if (Entry == NULL) {
187 return EFI_INVALID_PARAMETER;
188 }
189
190 Status = EfiAcquireLockOrFail (&mPrivate.NonFmpLock);
191 if (EFI_ERROR (Status)) {
192 return Status;
193 }
194
195 Status = GetEsrtEntry (
196 &Entry->FwClass,
197 ESRT_FROM_NONFMP,
198 &EsrtEntryTmp
199 );
200
201 if (Status == EFI_NOT_FOUND) {
202 Status = InsertEsrtEntry (Entry, ESRT_FROM_NONFMP);
203 }
204
205 EfiReleaseLock (&mPrivate.NonFmpLock);
206
207 return Status;
208}
209
221EFIAPI
223 VOID
224 )
225{
226 EFI_STATUS Status;
227 UINTN Index1;
228 UINTN Index2;
229 UINTN Index3;
230 EFI_HANDLE *HandleBuffer;
232 UINTN NumberOfHandles;
233 UINTN *DescriptorSizeBuf;
234 EFI_FIRMWARE_IMAGE_DESCRIPTOR **FmpImageInfoBuf;
235 EFI_FIRMWARE_IMAGE_DESCRIPTOR *TempFmpImageInfo;
236 UINT8 *FmpImageInfoCountBuf;
237 UINT32 *FmpImageInfoDescriptorVerBuf;
238 UINTN ImageInfoSize;
239 UINT32 PackageVersion;
240 CHAR16 *PackageVersionName;
241 EFI_SYSTEM_RESOURCE_ENTRY *EsrtRepositoryNew;
242 UINTN EntryNumNew;
243
244 NumberOfHandles = 0;
245 EntryNumNew = 0;
246 FmpBuf = NULL;
247 HandleBuffer = NULL;
248 FmpImageInfoBuf = NULL;
249 FmpImageInfoCountBuf = NULL;
250 PackageVersionName = NULL;
251 DescriptorSizeBuf = NULL;
252 FmpImageInfoDescriptorVerBuf = NULL;
253 EsrtRepositoryNew = NULL;
254
255 //
256 // Get image information from all FMP protocol
257 //
258 Status = gBS->LocateHandleBuffer (
260 &gEfiFirmwareManagementProtocolGuid,
261 NULL,
262 &NumberOfHandles,
263 &HandleBuffer
264 );
265
266 if (Status == EFI_NOT_FOUND) {
267 EntryNumNew = 0;
268 goto UPDATE_REPOSITORY;
269 } else if (EFI_ERROR (Status)) {
270 goto END;
271 }
272
273 //
274 // Allocate buffer to hold new FMP ESRT Cache repository
275 //
276 EsrtRepositoryNew = AllocateZeroPool (PcdGet32 (PcdMaxFmpEsrtCacheNum) * sizeof (EFI_SYSTEM_RESOURCE_ENTRY));
277 if (EsrtRepositoryNew == NULL) {
278 Status = EFI_OUT_OF_RESOURCES;
279 goto END;
280 }
281
282 FmpBuf = AllocatePool (sizeof (EFI_FIRMWARE_MANAGEMENT_PROTOCOL *) * NumberOfHandles);
283 if (FmpBuf == NULL) {
284 Status = EFI_OUT_OF_RESOURCES;
285 goto END;
286 }
287
288 FmpImageInfoBuf = AllocateZeroPool (sizeof (EFI_FIRMWARE_IMAGE_DESCRIPTOR *) * NumberOfHandles);
289 if (FmpImageInfoBuf == NULL) {
290 Status = EFI_OUT_OF_RESOURCES;
291 goto END;
292 }
293
294 FmpImageInfoCountBuf = AllocateZeroPool (sizeof (UINT8) * NumberOfHandles);
295 if (FmpImageInfoCountBuf == NULL) {
296 Status = EFI_OUT_OF_RESOURCES;
297 goto END;
298 }
299
300 DescriptorSizeBuf = AllocateZeroPool (sizeof (UINTN) * NumberOfHandles);
301 if (DescriptorSizeBuf == NULL) {
302 Status = EFI_OUT_OF_RESOURCES;
303 goto END;
304 }
305
306 FmpImageInfoDescriptorVerBuf = AllocateZeroPool (sizeof (UINT32) * NumberOfHandles);
307 if (FmpImageInfoDescriptorVerBuf == NULL) {
308 Status = EFI_OUT_OF_RESOURCES;
309 goto END;
310 }
311
312 //
313 // Get all FmpImageInfo Descriptor into FmpImageInfoBuf
314 //
315 for (Index1 = 0; Index1 < NumberOfHandles; Index1++) {
316 Status = gBS->HandleProtocol (
317 HandleBuffer[Index1],
318 &gEfiFirmwareManagementProtocolGuid,
319 (VOID **)&FmpBuf[Index1]
320 );
321
322 if (EFI_ERROR (Status)) {
323 continue;
324 }
325
326 ImageInfoSize = 0;
327 Status = FmpBuf[Index1]->GetImageInfo (
328 FmpBuf[Index1],
329 &ImageInfoSize,
330 NULL,
331 NULL,
332 NULL,
333 NULL,
334 NULL,
335 NULL
336 );
337
338 if (Status == EFI_BUFFER_TOO_SMALL) {
339 FmpImageInfoBuf[Index1] = AllocateZeroPool (ImageInfoSize);
340 if (FmpImageInfoBuf[Index1] == NULL) {
341 Status = EFI_OUT_OF_RESOURCES;
342 goto END;
343 }
344 } else {
345 continue;
346 }
347
348 PackageVersionName = NULL;
349 Status = FmpBuf[Index1]->GetImageInfo (
350 FmpBuf[Index1],
351 &ImageInfoSize,
352 FmpImageInfoBuf[Index1],
353 &FmpImageInfoDescriptorVerBuf[Index1],
354 &FmpImageInfoCountBuf[Index1],
355 &DescriptorSizeBuf[Index1],
356 &PackageVersion,
357 &PackageVersionName
358 );
359
360 //
361 // If FMP GetInformation interface failed, skip this resource
362 //
363 if (EFI_ERROR (Status)) {
364 FmpImageInfoCountBuf[Index1] = 0;
365 continue;
366 }
367
368 if (PackageVersionName != NULL) {
369 FreePool (PackageVersionName);
370 }
371 }
372
373 //
374 // Create new FMP cache repository based on FmpImageInfoBuf
375 //
376 for (Index2 = 0; Index2 < NumberOfHandles; Index2++) {
377 TempFmpImageInfo = FmpImageInfoBuf[Index2];
378 for (Index3 = 0; Index3 < FmpImageInfoCountBuf[Index2]; Index3++) {
379 if ( ((TempFmpImageInfo->AttributesSupported & IMAGE_ATTRIBUTE_IN_USE) != 0)
380 && ((TempFmpImageInfo->AttributesSetting & IMAGE_ATTRIBUTE_IN_USE) != 0))
381 {
382 //
383 // Always put the first smallest version of Image info into ESRT cache
384 //
385 for (Index1 = 0; Index1 < EntryNumNew; Index1++) {
386 if (CompareGuid (&EsrtRepositoryNew[Index1].FwClass, &TempFmpImageInfo->ImageTypeId)) {
387 if (EsrtRepositoryNew[Index1].FwVersion > TempFmpImageInfo->Version) {
388 SetEsrtEntryFromFmpInfo (&EsrtRepositoryNew[Index1], TempFmpImageInfo, FmpImageInfoDescriptorVerBuf[Index2]);
389 }
390
391 break;
392 }
393 }
394
395 //
396 // New ImageTypeId can't be found in EsrtRepositoryNew. Create a new one
397 //
398 if (Index1 == EntryNumNew) {
399 SetEsrtEntryFromFmpInfo (&EsrtRepositoryNew[EntryNumNew], TempFmpImageInfo, FmpImageInfoDescriptorVerBuf[Index2]);
400 EntryNumNew++;
401 if (EntryNumNew >= PcdGet32 (PcdMaxFmpEsrtCacheNum)) {
402 break;
403 }
404 }
405 }
406
407 //
408 // Use DescriptorSize to move ImageInfo Pointer to stay compatible with different ImageInfo version
409 //
410 TempFmpImageInfo = (EFI_FIRMWARE_IMAGE_DESCRIPTOR *)((UINT8 *)TempFmpImageInfo + DescriptorSizeBuf[Index2]);
411 }
412 }
413
414UPDATE_REPOSITORY:
415
416 Status = EfiAcquireLockOrFail (&mPrivate.FmpLock);
417 if (EFI_ERROR (Status)) {
418 return Status;
419 }
420
421 Status = gRT->SetVariable (
422 EFI_ESRT_FMP_VARIABLE_NAME,
423 &gEfiCallerIdGuid,
424 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
425 EntryNumNew * sizeof (EFI_SYSTEM_RESOURCE_ENTRY),
426 EsrtRepositoryNew
427 );
428
429 EfiReleaseLock (&mPrivate.FmpLock);
430
431END:
432 if (EsrtRepositoryNew != NULL) {
433 FreePool (EsrtRepositoryNew);
434 }
435
436 if (HandleBuffer != NULL) {
437 FreePool (HandleBuffer);
438 }
439
440 if (FmpBuf != NULL) {
441 FreePool (FmpBuf);
442 }
443
444 if (FmpImageInfoCountBuf != NULL) {
445 FreePool (FmpImageInfoCountBuf);
446 }
447
448 if (DescriptorSizeBuf != NULL) {
449 FreePool (DescriptorSizeBuf);
450 }
451
452 if (FmpImageInfoDescriptorVerBuf != NULL) {
453 FreePool (FmpImageInfoDescriptorVerBuf);
454 }
455
456 if (FmpImageInfoBuf != NULL) {
457 for (Index1 = 0; Index1 < NumberOfHandles; Index1++) {
458 if (FmpImageInfoBuf[Index1] != NULL) {
459 FreePool (FmpImageInfoBuf[Index1]);
460 }
461 }
462
463 FreePool (FmpImageInfoBuf);
464 }
465
466 return Status;
467}
468
477EFIAPI
479 VOID
480 )
481{
482 EFI_STATUS Status;
483 EDKII_VARIABLE_LOCK_PROTOCOL *VariableLock;
484
485 //
486 // Mark ACPI_GLOBAL_VARIABLE variable to read-only if the Variable Lock protocol exists
487 //
488 Status = gBS->LocateProtocol (&gEdkiiVariableLockProtocolGuid, NULL, (VOID **)&VariableLock);
489 if (!EFI_ERROR (Status)) {
490 Status = VariableLock->RequestToLock (VariableLock, EFI_ESRT_FMP_VARIABLE_NAME, &gEfiCallerIdGuid);
491 DEBUG ((DEBUG_INFO, "EsrtDxe Lock EsrtFmp Variable Status 0x%x", Status));
492
493 Status = VariableLock->RequestToLock (VariableLock, EFI_ESRT_NONFMP_VARIABLE_NAME, &gEfiCallerIdGuid);
494 DEBUG ((DEBUG_INFO, "EsrtDxe Lock EsrtNonFmp Variable Status 0x%x", Status));
495 }
496
497 return Status;
498}
499
508VOID
509EFIAPI
511 IN EFI_EVENT Event,
512 IN VOID *Context
513 )
514{
515 EFI_STATUS Status;
516 EFI_SYSTEM_RESOURCE_TABLE *EsrtTable;
517 EFI_SYSTEM_RESOURCE_ENTRY *FmpEsrtRepository;
518 EFI_SYSTEM_RESOURCE_ENTRY *NonFmpEsrtRepository;
519 UINTN FmpRepositorySize;
520 UINTN NonFmpRepositorySize;
521
522 FmpEsrtRepository = NULL;
523 NonFmpEsrtRepository = NULL;
524 FmpRepositorySize = 0;
525 NonFmpRepositorySize = 0;
526
527 Status = EfiAcquireLockOrFail (&mPrivate.NonFmpLock);
528 if (EFI_ERROR (Status)) {
529 return;
530 }
531
532 Status = GetVariable2 (
533 EFI_ESRT_NONFMP_VARIABLE_NAME,
534 &gEfiCallerIdGuid,
535 (VOID **)&NonFmpEsrtRepository,
536 &NonFmpRepositorySize
537 );
538
539 if (EFI_ERROR (Status)) {
540 NonFmpRepositorySize = 0;
541 }
542
543 if (NonFmpRepositorySize % sizeof (EFI_SYSTEM_RESOURCE_ENTRY) != 0) {
544 DEBUG ((DEBUG_ERROR, "NonFmp Repository Corrupt. Need to rebuild NonFmp Repository.\n"));
545 NonFmpRepositorySize = 0;
546 }
547
548 EfiReleaseLock (&mPrivate.NonFmpLock);
549
550 Status = EfiAcquireLockOrFail (&mPrivate.FmpLock);
551 Status = GetVariable2 (
552 EFI_ESRT_FMP_VARIABLE_NAME,
553 &gEfiCallerIdGuid,
554 (VOID **)&FmpEsrtRepository,
555 &FmpRepositorySize
556 );
557
558 if (EFI_ERROR (Status)) {
559 FmpRepositorySize = 0;
560 }
561
562 if (FmpRepositorySize % sizeof (EFI_SYSTEM_RESOURCE_ENTRY) != 0) {
563 DEBUG ((DEBUG_ERROR, "Fmp Repository Corrupt. Need to rebuild Fmp Repository.\n"));
564 FmpRepositorySize = 0;
565 }
566
567 EfiReleaseLock (&mPrivate.FmpLock);
568
569 //
570 // Skip ESRT table publish if no ESRT entry exists
571 //
572 if (NonFmpRepositorySize + FmpRepositorySize == 0) {
573 goto EXIT;
574 }
575
576 EsrtTable = AllocatePool (sizeof (EFI_SYSTEM_RESOURCE_TABLE) + NonFmpRepositorySize + FmpRepositorySize);
577 if (EsrtTable == NULL) {
578 DEBUG ((DEBUG_ERROR, "Esrt table memory allocation failure\n"));
579 goto EXIT;
580 }
581
583 EsrtTable->FwResourceCount = (UINT32)((NonFmpRepositorySize + FmpRepositorySize) / sizeof (EFI_SYSTEM_RESOURCE_ENTRY));
584 EsrtTable->FwResourceCountMax = PcdGet32 (PcdMaxNonFmpEsrtCacheNum) + PcdGet32 (PcdMaxFmpEsrtCacheNum);
585
586 if ((NonFmpRepositorySize != 0) && (NonFmpEsrtRepository != NULL)) {
587 CopyMem (EsrtTable + 1, NonFmpEsrtRepository, NonFmpRepositorySize);
588 }
589
590 if ((FmpRepositorySize != 0) && (FmpEsrtRepository != NULL)) {
591 CopyMem ((UINT8 *)(EsrtTable + 1) + NonFmpRepositorySize, FmpEsrtRepository, FmpRepositorySize);
592 }
593
594 //
595 // Publish Esrt to system config table
596 //
597 Status = gBS->InstallConfigurationTable (&gEfiSystemResourceTableGuid, EsrtTable);
598
599 //
600 // Only one successful install
601 //
602 gBS->CloseEvent (Event);
603
604EXIT:
605
606 if (FmpEsrtRepository != NULL) {
607 FreePool (FmpEsrtRepository);
608 }
609
610 if (NonFmpEsrtRepository != NULL) {
611 FreePool (NonFmpEsrtRepository);
612 }
613}
614
627EFIAPI
629 IN EFI_HANDLE ImageHandle,
630 IN EFI_SYSTEM_TABLE *SystemTable
631 )
632{
633 EFI_STATUS Status;
634
635 EfiInitializeLock (&mPrivate.FmpLock, TPL_CALLBACK);
636 EfiInitializeLock (&mPrivate.NonFmpLock, TPL_CALLBACK);
637
638 //
639 // Install Esrt management Protocol
640 //
641 Status = gBS->InstallMultipleProtocolInterfaces (
642 &mPrivate.Handle,
643 &gEsrtManagementProtocolGuid,
644 &mEsrtManagementProtocolTemplate,
645 NULL
646 );
647 ASSERT_EFI_ERROR (Status);
648
649 //
650 // Register notify function to install Esrt Table on ReadyToBoot Event.
651 //
652 Status = gBS->CreateEventEx (
653 EVT_NOTIFY_SIGNAL,
654 TPL_CALLBACK,
656 NULL,
657 &gEfiEventReadyToBootGuid,
658 &mPrivate.Event
659 );
660 ASSERT_EFI_ERROR (Status);
661
662 return EFI_SUCCESS;
663}
UINT64 UINTN
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
BOOLEAN EFIAPI CompareGuid(IN CONST GUID *Guid1, IN CONST GUID *Guid2)
Definition: MemLibGuid.c:73
VOID *EFIAPI AllocateZeroPool(IN UINTN AllocationSize)
VOID EFIAPI FreePool(IN VOID *Buffer)
EFI_STATUS EFIAPI EsrtDxeLockEsrtRepository(VOID)
Definition: EsrtDxe.c:478
EFI_STATUS EFIAPI EsrtDxeEntryPoint(IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable)
Definition: EsrtDxe.c:628
EFI_STATUS EFIAPI EsrtDxeUpdateEsrtEntry(IN EFI_SYSTEM_RESOURCE_ENTRY *Entry)
Definition: EsrtDxe.c:98
VOID EFIAPI EsrtReadyToBootEventNotify(IN EFI_EVENT Event, IN VOID *Context)
Definition: EsrtDxe.c:510
EFI_STATUS EFIAPI EsrtDxeSyncFmp(VOID)
Definition: EsrtDxe.c:222
EFI_STATUS EFIAPI EsrtDxeRegisterEsrtEntry(IN EFI_SYSTEM_RESOURCE_ENTRY *Entry)
Definition: EsrtDxe.c:179
EFI_STATUS EFIAPI EsrtDxeUnRegisterEsrtEntry(IN EFI_GUID *FwClass)
Definition: EsrtDxe.c:145
EFI_STATUS EFIAPI EsrtDxeGetEsrtEntry(IN EFI_GUID *FwClass, IN OUT EFI_SYSTEM_RESOURCE_ENTRY *Entry)
Definition: EsrtDxe.c:38
VOID SetEsrtEntryFromFmpInfo(IN OUT EFI_SYSTEM_RESOURCE_ENTRY *EsrtEntry, IN EFI_FIRMWARE_IMAGE_DESCRIPTOR *FmpImageInfo, IN UINT32 DescriptorVersion)
Definition: EsrtImpl.c:434
EFI_STATUS DeleteEsrtEntry(IN EFI_GUID *FwClass, IN UINTN Attribute)
Definition: EsrtImpl.c:209
EFI_STATUS GetEsrtEntry(IN EFI_GUID *FwClass, IN UINTN Attribute, OUT EFI_SYSTEM_RESOURCE_ENTRY *Entry)
Definition: EsrtImpl.c:23
EFI_STATUS UpdateEsrtEntry(IN EFI_SYSTEM_RESOURCE_ENTRY *Entry, UINTN Attribute)
Definition: EsrtImpl.c:310
EFI_STATUS InsertEsrtEntry(IN EFI_SYSTEM_RESOURCE_ENTRY *Entry, UINTN Attribute)
Definition: EsrtImpl.c:92
#define IMAGE_ATTRIBUTE_IN_USE
EFI_RUNTIME_SERVICES * gRT
#define NULL
Definition: Base.h:319
#define IN
Definition: Base.h:279
#define OUT
Definition: Base.h:284
#define ASSERT_EFI_ERROR(StatusParameter)
Definition: DebugLib.h:462
#define DEBUG(Expression)
Definition: DebugLib.h:434
#define PcdGet32(TokenName)
Definition: PcdLib.h:362
VOID *EFIAPI AllocatePool(IN UINTN AllocationSize)
#define EFI_SYSTEM_RESOURCE_TABLE_FIRMWARE_RESOURCE_VERSION
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
VOID * EFI_EVENT
Definition: UefiBaseType.h:37
VOID * EFI_HANDLE
Definition: UefiBaseType.h:33
#define EFI_SUCCESS
Definition: UefiBaseType.h:112
EFI_BOOT_SERVICES * gBS
VOID EFIAPI EfiReleaseLock(IN EFI_LOCK *Lock)
Definition: UefiLib.c:499
EFI_STATUS EFIAPI EfiAcquireLockOrFail(IN EFI_LOCK *Lock)
Definition: UefiLib.c:463
EFI_STATUS EFIAPI GetVariable2(IN CONST CHAR16 *Name, IN CONST EFI_GUID *Guid, OUT VOID **Value, OUT UINTN *Size OPTIONAL)
Definition: UefiLib.c:1317
EFI_LOCK *EFIAPI EfiInitializeLock(IN OUT EFI_LOCK *Lock, IN EFI_TPL Priority)
Definition: UefiLib.c:405
#define EFI_VARIABLE_NON_VOLATILE
@ ByProtocol
Definition: UefiSpec.h:1518
Definition: Base.h:213