MdeModulePkg/DxeCapsuleLibFmp: clone ESRT for runtime access
[mirror_edk2.git] / MdeModulePkg / Library / DxeCapsuleLibFmp / DxeCapsuleRuntime.c
1 /** @file\r
2   Capsule library runtime support.\r
3 \r
4   Copyright (c) 2016 - 2017, Intel Corporation. All rights reserved.<BR>\r
5   SPDX-License-Identifier: BSD-2-Clause-Patent\r
6 \r
7 **/\r
8 \r
9 #include <PiDxe.h>\r
10 \r
11 #include <Guid/FmpCapsule.h>\r
12 #include <Guid/SystemResourceTable.h>\r
13 #include <Guid/EventGroup.h>\r
14 \r
15 #include <Library/BaseLib.h>\r
16 #include <Library/DebugLib.h>\r
17 #include <Library/BaseMemoryLib.h>\r
18 #include <Library/DxeServicesTableLib.h>\r
19 #include <Library/UefiBootServicesTableLib.h>\r
20 #include <Library/UefiRuntimeServicesTableLib.h>\r
21 #include <Library/MemoryAllocationLib.h>\r
22 \r
23 extern EFI_SYSTEM_RESOURCE_TABLE *mEsrtTable;\r
24 extern BOOLEAN                   mIsVirtualAddrConverted;\r
25 EFI_EVENT                 mDxeRuntimeCapsuleLibVirtualAddressChangeEvent  = NULL;\r
26 EFI_EVENT                 mDxeRuntimeCapsuleLibReadyToBootEvent  = NULL;\r
27 \r
28 /**\r
29   Convert EsrtTable physical address to virtual address.\r
30 \r
31   @param[in] Event      Event whose notification function is being invoked.\r
32   @param[in] Context    The pointer to the notification function's context, which\r
33                         is implementation-dependent.\r
34 **/\r
35 VOID\r
36 EFIAPI\r
37 DxeCapsuleLibVirtualAddressChangeEvent (\r
38   IN  EFI_EVENT   Event,\r
39   IN  VOID        *Context\r
40   )\r
41 {\r
42   gRT->ConvertPointer (EFI_OPTIONAL_PTR, (VOID **)&mEsrtTable);\r
43   mIsVirtualAddrConverted = TRUE;\r
44 }\r
45 \r
46 /**\r
47   Notify function for event group EFI_EVENT_GROUP_READY_TO_BOOT.\r
48 \r
49   @param[in]  Event   The Event that is being processed.\r
50   @param[in]  Context The Event Context.\r
51 \r
52 **/\r
53 STATIC\r
54 VOID\r
55 EFIAPI\r
56 DxeCapsuleLibReadyToBootEventNotify (\r
57   IN EFI_EVENT        Event,\r
58   IN VOID             *Context\r
59   )\r
60 {\r
61   UINTN                       Index;\r
62   EFI_CONFIGURATION_TABLE     *ConfigEntry;\r
63   EFI_SYSTEM_RESOURCE_TABLE   *EsrtTable;\r
64 \r
65   //\r
66   // Get Esrt table first\r
67   //\r
68   ConfigEntry = gST->ConfigurationTable;\r
69   for (Index = 0; Index < gST->NumberOfTableEntries; Index++) {\r
70     if (CompareGuid(&gEfiSystemResourceTableGuid, &ConfigEntry->VendorGuid)) {\r
71       break;\r
72     }\r
73     ConfigEntry++;\r
74   }\r
75 \r
76   //\r
77   // If no Esrt table installed in Configure Table\r
78   //\r
79   if (Index < gST->NumberOfTableEntries) {\r
80     //\r
81     // Search Esrt to check given capsule is qualified\r
82     //\r
83     EsrtTable = (EFI_SYSTEM_RESOURCE_TABLE *) ConfigEntry->VendorTable;\r
84 \r
85     mEsrtTable = AllocateRuntimeCopyPool (\r
86                    sizeof (EFI_SYSTEM_RESOURCE_TABLE) +\r
87                    EsrtTable->FwResourceCount * sizeof (EFI_SYSTEM_RESOURCE_ENTRY),\r
88                    EsrtTable);\r
89     ASSERT (mEsrtTable != NULL);\r
90 \r
91     //\r
92     // Set FwResourceCountMax to a sane value.\r
93     //\r
94     mEsrtTable->FwResourceCountMax = mEsrtTable->FwResourceCount;\r
95   }\r
96 }\r
97 \r
98 /**\r
99   The constructor function hook VirtualAddressChange event to use ESRT table as capsule routing table.\r
100 \r
101   @param  ImageHandle   The firmware allocated handle for the EFI image.\r
102   @param  SystemTable   A pointer to the EFI System Table.\r
103 \r
104   @retval EFI_SUCCESS   The constructor successfully .\r
105 **/\r
106 EFI_STATUS\r
107 EFIAPI\r
108 DxeRuntimeCapsuleLibConstructor (\r
109   IN EFI_HANDLE         ImageHandle,\r
110   IN EFI_SYSTEM_TABLE   *SystemTable\r
111   )\r
112 {\r
113   EFI_STATUS     Status;\r
114 \r
115   //\r
116   // Make sure we can handle virtual address changes.\r
117   //\r
118   Status = gBS->CreateEventEx (\r
119                   EVT_NOTIFY_SIGNAL,\r
120                   TPL_NOTIFY,\r
121                   DxeCapsuleLibVirtualAddressChangeEvent,\r
122                   NULL,\r
123                   &gEfiEventVirtualAddressChangeGuid,\r
124                   &mDxeRuntimeCapsuleLibVirtualAddressChangeEvent\r
125                   );\r
126   ASSERT_EFI_ERROR (Status);\r
127 \r
128   //\r
129   // Register notify function to cache the FMP capsule GUIDs at ReadyToBoot.\r
130   //\r
131   Status = gBS->CreateEventEx (\r
132                   EVT_NOTIFY_SIGNAL,\r
133                   TPL_CALLBACK,\r
134                   DxeCapsuleLibReadyToBootEventNotify,\r
135                   NULL,\r
136                   &gEfiEventReadyToBootGuid,\r
137                   &mDxeRuntimeCapsuleLibReadyToBootEvent\r
138                   );\r
139   ASSERT_EFI_ERROR (Status);\r
140 \r
141   return EFI_SUCCESS;\r
142 }\r
143 \r
144 /**\r
145   The destructor function closes the VirtualAddressChange event.\r
146 \r
147   @param  ImageHandle   The firmware allocated handle for the EFI image.\r
148   @param  SystemTable   A pointer to the EFI System Table.\r
149 \r
150   @retval EFI_SUCCESS   The destructor completed successfully.\r
151 **/\r
152 EFI_STATUS\r
153 EFIAPI\r
154 DxeRuntimeCapsuleLibDestructor (\r
155   IN EFI_HANDLE         ImageHandle,\r
156   IN EFI_SYSTEM_TABLE   *SystemTable\r
157   )\r
158 {\r
159   EFI_STATUS    Status;\r
160 \r
161   //\r
162   // Close the VirtualAddressChange event.\r
163   //\r
164   Status = gBS->CloseEvent (mDxeRuntimeCapsuleLibVirtualAddressChangeEvent);\r
165   ASSERT_EFI_ERROR (Status);\r
166 \r
167   //\r
168   // Close the ReadyToBoot event.\r
169   //\r
170   Status = gBS->CloseEvent (mDxeRuntimeCapsuleLibReadyToBootEvent);\r
171   ASSERT_EFI_ERROR (Status);\r
172 \r
173   return EFI_SUCCESS;\r
174 }\r