1 /** @file
2   Esrt management module.
3 
4 Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
6 
7 **/
8 #include "EsrtImpl.h"
9 
10 
11 //
12 // Module globals.
13 //
14 
15 ESRT_PRIVATE_DATA mPrivate;
16 
17 ESRT_MANAGEMENT_PROTOCOL  mEsrtManagementProtocolTemplate = {
18                             EsrtDxeGetEsrtEntry,
19                             EsrtDxeUpdateEsrtEntry,
20                             EsrtDxeRegisterEsrtEntry,
21                             EsrtDxeUnRegisterEsrtEntry,
22                             EsrtDxeSyncFmp,
23                             EsrtDxeLockEsrtRepository
24                             };
25 
26 /**
27   Get ESRT entry from ESRT Cache by FwClass Guid
28 
29   @param[in]       FwClass                FwClass of Esrt entry to get
30   @param[in, out]  Entry                  Esrt entry returned
31 
32   @retval EFI_SUCCESS                   The variable saving this Esrt Entry exists.
33   @retval EF_NOT_FOUND                  No correct variable found.
34   @retval EFI_WRITE_PROTECTED           ESRT Cache repository is locked
35 
36 **/
37 EFI_STATUS
38 EFIAPI
EsrtDxeGetEsrtEntry(IN EFI_GUID * FwClass,IN OUT EFI_SYSTEM_RESOURCE_ENTRY * Entry)39 EsrtDxeGetEsrtEntry(
40   IN     EFI_GUID                  *FwClass,
41   IN OUT EFI_SYSTEM_RESOURCE_ENTRY *Entry
42   )
43 {
44   EFI_STATUS                Status;
45 
46   if (FwClass == NULL || Entry == NULL) {
47     return EFI_INVALID_PARAMETER;
48   }
49 
50   Status = EfiAcquireLockOrFail (&mPrivate.NonFmpLock);
51   if (EFI_ERROR (Status)) {
52     return Status;
53   }
54 
55   //
56   // Find in Non-FMP Cached Esrt Repository
57   //
58   Status = GetEsrtEntry(
59              FwClass,
60              ESRT_FROM_NONFMP,
61              Entry
62              );
63 
64   EfiReleaseLock(&mPrivate.NonFmpLock);
65 
66   if (EFI_ERROR(Status)) {
67     Status = EfiAcquireLockOrFail (&mPrivate.FmpLock);
68     if (EFI_ERROR (Status)) {
69       return Status;
70     }
71 
72     //
73     // Find in FMP Cached Esrt NV Variable
74     //
75     Status = GetEsrtEntry(
76                FwClass,
77                ESRT_FROM_FMP,
78                Entry
79                );
80 
81     EfiReleaseLock(&mPrivate.FmpLock);
82   }
83 
84   return Status;
85 }
86 
87 /**
88   Update one ESRT entry in ESRT Cache.
89 
90   @param[in]  Entry                         Esrt entry to be updated
91 
92   @retval EFI_SUCCESS                   Successfully update an ESRT entry in cache.
93   @retval EFI_INVALID_PARAMETER         Entry does't exist in ESRT Cache
94   @retval EFI_WRITE_PROTECTED           ESRT Cache repositoy is locked
95 
96 **/
97 EFI_STATUS
98 EFIAPI
EsrtDxeUpdateEsrtEntry(IN EFI_SYSTEM_RESOURCE_ENTRY * Entry)99 EsrtDxeUpdateEsrtEntry(
100   IN EFI_SYSTEM_RESOURCE_ENTRY *Entry
101   )
102 {
103   EFI_STATUS                Status;
104 
105   if (Entry == NULL) {
106     return EFI_INVALID_PARAMETER;
107   }
108 
109   Status = EfiAcquireLockOrFail (&mPrivate.FmpLock);
110   if (EFI_ERROR (Status)) {
111     return Status;
112   }
113 
114   Status = UpdateEsrtEntry(Entry, ESRT_FROM_FMP);
115 
116   if (!EFI_ERROR(Status)) {
117     EfiReleaseLock(&mPrivate.FmpLock);
118     return Status;
119   }
120   EfiReleaseLock(&mPrivate.FmpLock);
121 
122 
123   Status = EfiAcquireLockOrFail (&mPrivate.NonFmpLock);
124   if (EFI_ERROR (Status)) {
125     return Status;
126   }
127 
128   Status = UpdateEsrtEntry(Entry, ESRT_FROM_NONFMP);
129 
130   EfiReleaseLock(&mPrivate.NonFmpLock);
131 
132   return Status;
133 }
134 
135 /**
136   Non-FMP instance to unregister Esrt Entry from ESRT Cache.
137 
138   @param[in]    FwClass                FwClass of Esrt entry to Unregister
139 
140   @retval EFI_SUCCESS             Insert all entries Successfully
141   @retval EFI_NOT_FOUND           Entry of FwClass does not exsit
142 
143 **/
144 EFI_STATUS
145 EFIAPI
EsrtDxeUnRegisterEsrtEntry(IN EFI_GUID * FwClass)146 EsrtDxeUnRegisterEsrtEntry(
147   IN  EFI_GUID        *FwClass
148   )
149 {
150   EFI_STATUS Status;
151 
152   if (FwClass == NULL) {
153     return EFI_INVALID_PARAMETER;
154   }
155 
156   Status = EfiAcquireLockOrFail (&mPrivate.NonFmpLock);
157   if (EFI_ERROR (Status)) {
158     return Status;
159   }
160 
161   Status = DeleteEsrtEntry(FwClass, ESRT_FROM_NONFMP);
162 
163   EfiReleaseLock(&mPrivate.NonFmpLock);
164 
165   return Status;
166 }
167 
168 /**
169   Non-FMP instance to register one ESRT entry into ESRT Cache.
170 
171   @param[in]  Entry                Esrt entry to be set
172 
173   @retval EFI_SUCCESS              Successfully set a variable.
174   @retval EFI_INVALID_PARAMETER    ESRT Entry is already exist
175   @retval EFI_OUT_OF_RESOURCES     Non-FMP ESRT repository is full
176 
177 **/
178 EFI_STATUS
179 EFIAPI
EsrtDxeRegisterEsrtEntry(IN EFI_SYSTEM_RESOURCE_ENTRY * Entry)180 EsrtDxeRegisterEsrtEntry(
181   IN EFI_SYSTEM_RESOURCE_ENTRY *Entry
182   )
183 {
184   EFI_STATUS                Status;
185   EFI_SYSTEM_RESOURCE_ENTRY EsrtEntryTmp;
186 
187   if (Entry == NULL) {
188     return EFI_INVALID_PARAMETER;
189   }
190 
191   Status = EfiAcquireLockOrFail (&mPrivate.NonFmpLock);
192   if (EFI_ERROR (Status)) {
193     return Status;
194   }
195 
196   Status = GetEsrtEntry(
197              &Entry->FwClass,
198              ESRT_FROM_NONFMP,
199              &EsrtEntryTmp
200              );
201 
202   if (Status == EFI_NOT_FOUND) {
203     Status = InsertEsrtEntry(Entry, ESRT_FROM_NONFMP);
204   }
205 
206   EfiReleaseLock(&mPrivate.NonFmpLock);
207 
208   return Status;
209 }
210 
211 /**
212   This function syn up Cached ESRT with data from FMP instances
213   Function should be called after Connect All in order to locate all FMP protocols
214   installed.
215 
216   @retval EFI_SUCCESS                      Successfully sync cache repository from FMP instances
217   @retval EFI_NOT_FOUND                   No FMP Instance are found
218   @retval EFI_OUT_OF_RESOURCES     Resource allocaton fail
219 
220 **/
221 EFI_STATUS
222 EFIAPI
EsrtDxeSyncFmp(VOID)223 EsrtDxeSyncFmp(
224   VOID
225   )
226 {
227   EFI_STATUS                                Status;
228   UINTN                                     Index1;
229   UINTN                                     Index2;
230   UINTN                                     Index3;
231   EFI_HANDLE                                *HandleBuffer;
232   EFI_FIRMWARE_MANAGEMENT_PROTOCOL          **FmpBuf;
233   UINTN                                     NumberOfHandles;
234   UINTN                                     *DescriptorSizeBuf;
235   EFI_FIRMWARE_IMAGE_DESCRIPTOR             **FmpImageInfoBuf;
236   EFI_FIRMWARE_IMAGE_DESCRIPTOR             *TempFmpImageInfo;
237   UINT8                                     *FmpImageInfoCountBuf;
238   UINT32                                    *FmpImageInfoDescriptorVerBuf;
239   UINTN                                     ImageInfoSize;
240   UINT32                                    PackageVersion;
241   CHAR16                                    *PackageVersionName;
242   EFI_SYSTEM_RESOURCE_ENTRY                 *EsrtRepositoryNew;
243   UINTN                                     EntryNumNew;
244 
245   NumberOfHandles              = 0;
246   EntryNumNew                  = 0;
247   FmpBuf                       = NULL;
248   HandleBuffer                 = NULL;
249   FmpImageInfoBuf              = NULL;
250   FmpImageInfoCountBuf         = NULL;
251   PackageVersionName           = NULL;
252   DescriptorSizeBuf            = NULL;
253   FmpImageInfoDescriptorVerBuf = NULL;
254   EsrtRepositoryNew            = NULL;
255 
256   //
257   // Get image information from all FMP protocol
258   //
259   Status = gBS->LocateHandleBuffer (
260                   ByProtocol,
261                   &gEfiFirmwareManagementProtocolGuid,
262                   NULL,
263                   &NumberOfHandles,
264                   &HandleBuffer
265                   );
266 
267 
268   if (Status == EFI_NOT_FOUND) {
269     EntryNumNew = 0;
270     goto UPDATE_REPOSITORY;
271   } else if (EFI_ERROR(Status)){
272     goto END;
273   }
274 
275   //
276   // Allocate buffer to hold new FMP ESRT Cache repository
277   //
278   EsrtRepositoryNew = AllocateZeroPool(PcdGet32(PcdMaxFmpEsrtCacheNum) * sizeof(EFI_SYSTEM_RESOURCE_ENTRY));
279   if (EsrtRepositoryNew == NULL) {
280     Status = EFI_OUT_OF_RESOURCES;
281     goto END;
282   }
283 
284   FmpBuf = AllocatePool(sizeof(EFI_FIRMWARE_MANAGEMENT_PROTOCOL *) * NumberOfHandles);
285   if (FmpBuf == NULL) {
286     Status = EFI_OUT_OF_RESOURCES;
287     goto END;
288   }
289 
290   FmpImageInfoBuf = AllocateZeroPool(sizeof(EFI_FIRMWARE_IMAGE_DESCRIPTOR *) * NumberOfHandles);
291   if (FmpImageInfoBuf == NULL) {
292     Status = EFI_OUT_OF_RESOURCES;
293     goto END;
294   }
295 
296   FmpImageInfoCountBuf = AllocateZeroPool(sizeof(UINT8) * NumberOfHandles);
297   if (FmpImageInfoCountBuf == NULL) {
298     Status = EFI_OUT_OF_RESOURCES;
299     goto END;
300   }
301 
302   DescriptorSizeBuf = AllocateZeroPool(sizeof(UINTN) * NumberOfHandles);
303   if (DescriptorSizeBuf == NULL) {
304     Status = EFI_OUT_OF_RESOURCES;
305     goto END;
306   }
307 
308   FmpImageInfoDescriptorVerBuf = AllocateZeroPool(sizeof(UINT32) * NumberOfHandles);
309    if (FmpImageInfoDescriptorVerBuf == NULL) {
310     Status = EFI_OUT_OF_RESOURCES;
311     goto END;
312   }
313 
314   //
315   // Get all FmpImageInfo Descriptor into FmpImageInfoBuf
316   //
317   for (Index1 = 0; Index1 < NumberOfHandles; Index1++){
318     Status = gBS->HandleProtocol(
319                     HandleBuffer[Index1],
320                     &gEfiFirmwareManagementProtocolGuid,
321                     (VOID **)&FmpBuf[Index1]
322                     );
323 
324     if (EFI_ERROR(Status)) {
325       continue;
326     }
327 
328     ImageInfoSize = 0;
329     Status = FmpBuf[Index1]->GetImageInfo (
330                                FmpBuf[Index1],
331                                &ImageInfoSize,
332                                NULL,
333                                NULL,
334                                NULL,
335                                NULL,
336                                NULL,
337                                NULL
338                                );
339 
340     if (Status == EFI_BUFFER_TOO_SMALL) {
341       FmpImageInfoBuf[Index1] = AllocateZeroPool(ImageInfoSize);
342       if (FmpImageInfoBuf[Index1] == NULL) {
343         Status = EFI_OUT_OF_RESOURCES;
344         goto END;
345       }
346     } else {
347       continue;
348     }
349 
350     PackageVersionName = NULL;
351     Status = FmpBuf[Index1]->GetImageInfo (
352                                FmpBuf[Index1],
353                                &ImageInfoSize,
354                                FmpImageInfoBuf[Index1],
355                                &FmpImageInfoDescriptorVerBuf[Index1],
356                                &FmpImageInfoCountBuf[Index1],
357                                &DescriptorSizeBuf[Index1],
358                                &PackageVersion,
359                                &PackageVersionName
360                                );
361 
362     //
363     // If FMP GetInformation interface failed, skip this resource
364     //
365     if (EFI_ERROR(Status)){
366       FmpImageInfoCountBuf[Index1] = 0;
367       continue;
368     }
369 
370     if (PackageVersionName != NULL) {
371       FreePool(PackageVersionName);
372     }
373   }
374 
375   //
376   // Create new FMP cache repository based on FmpImageInfoBuf
377   //
378   for (Index2 = 0; Index2 < NumberOfHandles; Index2++){
379     TempFmpImageInfo = FmpImageInfoBuf[Index2];
380     for (Index3 = 0; Index3 < FmpImageInfoCountBuf[Index2]; Index3++){
381       if ((TempFmpImageInfo->AttributesSupported & IMAGE_ATTRIBUTE_IN_USE) != 0
382       && (TempFmpImageInfo->AttributesSetting & IMAGE_ATTRIBUTE_IN_USE) != 0){
383         //
384         // Always put the first smallest version of Image info into ESRT cache
385         //
386         for(Index1 = 0; Index1 < EntryNumNew; Index1++) {
387           if (CompareGuid(&EsrtRepositoryNew[Index1].FwClass, &TempFmpImageInfo->ImageTypeId)) {
388             if(EsrtRepositoryNew[Index1].FwVersion > TempFmpImageInfo->Version) {
389               SetEsrtEntryFromFmpInfo(&EsrtRepositoryNew[Index1], TempFmpImageInfo, FmpImageInfoDescriptorVerBuf[Index2]);
390             }
391             break;
392           }
393         }
394         //
395         // New ImageTypeId can't be found in EsrtRepositoryNew. Create a new one
396         //
397         if (Index1 == EntryNumNew){
398           SetEsrtEntryFromFmpInfo(&EsrtRepositoryNew[EntryNumNew], TempFmpImageInfo, FmpImageInfoDescriptorVerBuf[Index2]);
399           EntryNumNew++;
400           if (EntryNumNew >= PcdGet32(PcdMaxFmpEsrtCacheNum)) {
401             break;
402           }
403         }
404       }
405 
406       //
407       // Use DescriptorSize to move ImageInfo Pointer to stay compatible with different ImageInfo version
408       //
409       TempFmpImageInfo = (EFI_FIRMWARE_IMAGE_DESCRIPTOR *)((UINT8 *)TempFmpImageInfo + DescriptorSizeBuf[Index2]);
410     }
411   }
412 
413 UPDATE_REPOSITORY:
414 
415   Status = EfiAcquireLockOrFail (&mPrivate.FmpLock);
416   if (EFI_ERROR (Status)) {
417     return Status;
418   }
419 
420   Status = gRT->SetVariable(
421                   EFI_ESRT_FMP_VARIABLE_NAME,
422                   &gEfiCallerIdGuid,
423                   EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
424                   EntryNumNew * sizeof(EFI_SYSTEM_RESOURCE_ENTRY),
425                   EsrtRepositoryNew
426                   );
427 
428   EfiReleaseLock(&mPrivate.FmpLock);
429 
430 END:
431   if (EsrtRepositoryNew != NULL) {
432     FreePool(EsrtRepositoryNew);
433   }
434 
435   if (HandleBuffer != NULL) {
436     FreePool(HandleBuffer);
437   }
438 
439   if (FmpBuf != NULL) {
440     FreePool(FmpBuf);
441   }
442 
443   if (FmpImageInfoCountBuf != NULL) {
444     FreePool(FmpImageInfoCountBuf);
445   }
446 
447   if (DescriptorSizeBuf != NULL) {
448     FreePool(DescriptorSizeBuf);
449   }
450 
451   if (FmpImageInfoDescriptorVerBuf != NULL) {
452     FreePool(FmpImageInfoDescriptorVerBuf);
453   }
454 
455   if (FmpImageInfoBuf != NULL) {
456     for (Index1 = 0; Index1 < NumberOfHandles; Index1++){
457       if (FmpImageInfoBuf[Index1] != NULL) {
458         FreePool(FmpImageInfoBuf[Index1]);
459       }
460     }
461     FreePool(FmpImageInfoBuf);
462   }
463 
464   return Status;
465 }
466 
467 /**
468   This function locks up Esrt repository to be readonly. It should be called
469   before gEfiEndOfDxeEventGroupGuid event signaled
470 
471   @retval EFI_SUCCESS              Locks up FMP Non-FMP repository successfully
472 
473 **/
474 EFI_STATUS
475 EFIAPI
EsrtDxeLockEsrtRepository(VOID)476 EsrtDxeLockEsrtRepository(
477   VOID
478   )
479 {
480   EFI_STATUS                    Status;
481   EDKII_VARIABLE_LOCK_PROTOCOL  *VariableLock;
482   //
483   // Mark ACPI_GLOBAL_VARIABLE variable to read-only if the Variable Lock protocol exists
484   //
485   Status = gBS->LocateProtocol (&gEdkiiVariableLockProtocolGuid, NULL, (VOID **) &VariableLock);
486   if (!EFI_ERROR (Status)) {
487     Status = VariableLock->RequestToLock (VariableLock, EFI_ESRT_FMP_VARIABLE_NAME, &gEfiCallerIdGuid);
488     DEBUG((EFI_D_INFO, "EsrtDxe Lock EsrtFmp Variable Status 0x%x", Status));
489 
490     Status = VariableLock->RequestToLock (VariableLock, EFI_ESRT_NONFMP_VARIABLE_NAME, &gEfiCallerIdGuid);
491     DEBUG((EFI_D_INFO, "EsrtDxe Lock EsrtNonFmp Variable Status 0x%x", Status));
492   }
493 
494   return Status;
495 }
496 
497 /**
498   Notify function for event group EFI_EVENT_GROUP_READY_TO_BOOT. This is used to
499   install the Esrt Table into system configuration table
500 
501   @param[in]  Event   The Event that is being processed.
502   @param[in]  Context The Event Context.
503 
504 **/
505 VOID
506 EFIAPI
EsrtReadyToBootEventNotify(IN EFI_EVENT Event,IN VOID * Context)507 EsrtReadyToBootEventNotify (
508   IN EFI_EVENT        Event,
509   IN VOID             *Context
510   )
511 {
512   EFI_STATUS                 Status;
513   EFI_SYSTEM_RESOURCE_TABLE  *EsrtTable;
514   EFI_SYSTEM_RESOURCE_ENTRY  *FmpEsrtRepository;
515   EFI_SYSTEM_RESOURCE_ENTRY  *NonFmpEsrtRepository;
516   UINTN                      FmpRepositorySize;
517   UINTN                      NonFmpRepositorySize;
518 
519 
520   FmpEsrtRepository    = NULL;
521   NonFmpEsrtRepository = NULL;
522   FmpRepositorySize    = 0;
523   NonFmpRepositorySize = 0;
524 
525   Status = EfiAcquireLockOrFail (&mPrivate.NonFmpLock);
526   if (EFI_ERROR (Status)) {
527     return;
528   }
529 
530   Status = GetVariable2 (
531              EFI_ESRT_NONFMP_VARIABLE_NAME,
532              &gEfiCallerIdGuid,
533              (VOID **) &NonFmpEsrtRepository,
534              &NonFmpRepositorySize
535              );
536 
537   if (EFI_ERROR(Status)) {
538     NonFmpRepositorySize = 0;
539   }
540 
541   if (NonFmpRepositorySize % sizeof(EFI_SYSTEM_RESOURCE_ENTRY) != 0) {
542     DEBUG((EFI_D_ERROR, "NonFmp Repository Corrupt. Need to rebuild NonFmp Repository.\n"));
543     NonFmpRepositorySize = 0;
544   }
545 
546   EfiReleaseLock(&mPrivate.NonFmpLock);
547 
548   Status = EfiAcquireLockOrFail (&mPrivate.FmpLock);
549   Status = GetVariable2 (
550              EFI_ESRT_FMP_VARIABLE_NAME,
551              &gEfiCallerIdGuid,
552              (VOID **) &FmpEsrtRepository,
553              &FmpRepositorySize
554              );
555 
556   if (EFI_ERROR(Status)) {
557     FmpRepositorySize = 0;
558   }
559 
560   if (FmpRepositorySize % sizeof(EFI_SYSTEM_RESOURCE_ENTRY) != 0) {
561     DEBUG((EFI_D_ERROR, "Fmp Repository Corrupt. Need to rebuild Fmp Repository.\n"));
562     FmpRepositorySize = 0;
563   }
564 
565   EfiReleaseLock(&mPrivate.FmpLock);
566 
567   //
568   // Skip ESRT table publish if no ESRT entry exists
569   //
570   if (NonFmpRepositorySize + FmpRepositorySize == 0) {
571     goto EXIT;
572   }
573 
574   EsrtTable = AllocatePool(sizeof(EFI_SYSTEM_RESOURCE_TABLE) + NonFmpRepositorySize + FmpRepositorySize);
575   if (EsrtTable == NULL) {
576     DEBUG ((EFI_D_ERROR, "Esrt table memory allocation failure\n"));
577     goto EXIT;
578   }
579 
580   EsrtTable->FwResourceVersion  = EFI_SYSTEM_RESOURCE_TABLE_FIRMWARE_RESOURCE_VERSION;
581   EsrtTable->FwResourceCount    = (UINT32)((NonFmpRepositorySize + FmpRepositorySize) / sizeof(EFI_SYSTEM_RESOURCE_ENTRY));
582   EsrtTable->FwResourceCountMax = PcdGet32(PcdMaxNonFmpEsrtCacheNum) + PcdGet32(PcdMaxFmpEsrtCacheNum);
583 
584   if (NonFmpRepositorySize != 0 && NonFmpEsrtRepository != NULL) {
585     CopyMem(EsrtTable + 1, NonFmpEsrtRepository, NonFmpRepositorySize);
586   }
587 
588   if (FmpRepositorySize != 0 && FmpEsrtRepository != NULL) {
589     CopyMem((UINT8 *)(EsrtTable + 1) + NonFmpRepositorySize, FmpEsrtRepository, FmpRepositorySize);
590   }
591 
592   //
593   // Publish Esrt to system config table
594   //
595   Status = gBS->InstallConfigurationTable (&gEfiSystemResourceTableGuid, EsrtTable);
596 
597   //
598   // Only one successful install
599   //
600   gBS->CloseEvent(Event);
601 
602 EXIT:
603 
604   if (FmpEsrtRepository != NULL) {
605     FreePool(FmpEsrtRepository);
606   }
607 
608   if (NonFmpEsrtRepository != NULL) {
609     FreePool(NonFmpEsrtRepository);
610   }
611 }
612 
613 /**
614   The module Entry Point of the Esrt DXE driver that manages cached ESRT repository
615   & publishes ESRT table
616 
617   @param[in]  ImageHandle    The firmware allocated handle for the EFI image.
618   @param[in]  SystemTable    A pointer to the EFI System Table.
619 
620   @retval EFI_SUCCESS    The entry point is executed successfully.
621   @retval Other          Some error occurs when executing this entry point.
622 
623 **/
624 EFI_STATUS
625 EFIAPI
EsrtDxeEntryPoint(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)626 EsrtDxeEntryPoint (
627   IN EFI_HANDLE         ImageHandle,
628   IN EFI_SYSTEM_TABLE   *SystemTable
629   )
630 {
631   EFI_STATUS                    Status;
632 
633   EfiInitializeLock (&mPrivate.FmpLock,    TPL_CALLBACK);
634   EfiInitializeLock (&mPrivate.NonFmpLock, TPL_CALLBACK);
635 
636   //
637   // Install Esrt management Protocol
638   //
639   Status = gBS->InstallMultipleProtocolInterfaces (
640                   &mPrivate.Handle,
641                   &gEsrtManagementProtocolGuid,
642                   &mEsrtManagementProtocolTemplate,
643                   NULL
644                   );
645   ASSERT_EFI_ERROR (Status);
646 
647   //
648   // Register notify function to install Esrt Table on ReadyToBoot Event.
649   //
650   Status = gBS->CreateEventEx (
651                   EVT_NOTIFY_SIGNAL,
652                   TPL_CALLBACK,
653                   EsrtReadyToBootEventNotify,
654                   NULL,
655                   &gEfiEventReadyToBootGuid,
656                   &mPrivate.Event
657                   );
658   ASSERT_EFI_ERROR (Status);
659 
660   return EFI_SUCCESS;
661 }
662