]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - MdeModulePkg/Core/PiSmmCore/Smi.c
MdeModulePkg PiSmmCore: Remove redundant functions
[mirror_edk2.git] / MdeModulePkg / Core / PiSmmCore / Smi.c
... / ...
CommitLineData
1/** @file\r
2 SMI management.\r
3\r
4 Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>\r
5 This program and the accompanying materials are licensed and made available\r
6 under the terms and conditions of the BSD License which accompanies this\r
7 distribution. The full text of the license may be found at\r
8 http://opensource.org/licenses/bsd-license.php\r
9\r
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12\r
13**/\r
14\r
15#include "PiSmmCore.h"\r
16\r
17LIST_ENTRY mSmiEntryList = INITIALIZE_LIST_HEAD_VARIABLE (mSmiEntryList);\r
18\r
19SMI_ENTRY mRootSmiEntry = {\r
20 SMI_ENTRY_SIGNATURE,\r
21 INITIALIZE_LIST_HEAD_VARIABLE (mRootSmiEntry.AllEntries),\r
22 {0},\r
23 INITIALIZE_LIST_HEAD_VARIABLE (mRootSmiEntry.SmiHandlers),\r
24};\r
25\r
26/**\r
27 Finds the SMI entry for the requested handler type.\r
28\r
29 @param HandlerType The type of the interrupt\r
30 @param Create Create a new entry if not found\r
31\r
32 @return SMI entry\r
33\r
34**/\r
35SMI_ENTRY *\r
36EFIAPI\r
37SmmCoreFindSmiEntry (\r
38 IN EFI_GUID *HandlerType,\r
39 IN BOOLEAN Create\r
40 )\r
41{\r
42 LIST_ENTRY *Link;\r
43 SMI_ENTRY *Item;\r
44 SMI_ENTRY *SmiEntry;\r
45\r
46 //\r
47 // Search the SMI entry list for the matching GUID\r
48 //\r
49 SmiEntry = NULL;\r
50 for (Link = mSmiEntryList.ForwardLink;\r
51 Link != &mSmiEntryList;\r
52 Link = Link->ForwardLink) {\r
53\r
54 Item = CR (Link, SMI_ENTRY, AllEntries, SMI_ENTRY_SIGNATURE);\r
55 if (CompareGuid (&Item->HandlerType, HandlerType)) {\r
56 //\r
57 // This is the SMI entry\r
58 //\r
59 SmiEntry = Item;\r
60 break;\r
61 }\r
62 }\r
63\r
64 //\r
65 // If the protocol entry was not found and Create is TRUE, then\r
66 // allocate a new entry\r
67 //\r
68 if ((SmiEntry == NULL) && Create) {\r
69 SmiEntry = AllocatePool (sizeof(SMI_ENTRY));\r
70 if (SmiEntry != NULL) {\r
71 //\r
72 // Initialize new SMI entry structure\r
73 //\r
74 SmiEntry->Signature = SMI_ENTRY_SIGNATURE;\r
75 CopyGuid ((VOID *)&SmiEntry->HandlerType, HandlerType);\r
76 InitializeListHead (&SmiEntry->SmiHandlers);\r
77\r
78 //\r
79 // Add it to SMI entry list\r
80 //\r
81 InsertTailList (&mSmiEntryList, &SmiEntry->AllEntries);\r
82 }\r
83 }\r
84 return SmiEntry;\r
85}\r
86\r
87/**\r
88 Manage SMI of a particular type.\r
89\r
90 @param HandlerType Points to the handler type or NULL for root SMI handlers.\r
91 @param Context Points to an optional context buffer.\r
92 @param CommBuffer Points to the optional communication buffer.\r
93 @param CommBufferSize Points to the size of the optional communication buffer.\r
94\r
95 @retval EFI_WARN_INTERRUPT_SOURCE_PENDING Interrupt source was processed successfully but not quiesced.\r
96 @retval EFI_INTERRUPT_PENDING One or more SMI sources could not be quiesced.\r
97 @retval EFI_NOT_FOUND Interrupt source was not handled or quiesced.\r
98 @retval EFI_SUCCESS Interrupt source was handled and quiesced.\r
99\r
100**/\r
101EFI_STATUS\r
102EFIAPI\r
103SmiManage (\r
104 IN CONST EFI_GUID *HandlerType,\r
105 IN CONST VOID *Context OPTIONAL,\r
106 IN OUT VOID *CommBuffer OPTIONAL,\r
107 IN OUT UINTN *CommBufferSize OPTIONAL\r
108 )\r
109{\r
110 LIST_ENTRY *Link;\r
111 LIST_ENTRY *Head;\r
112 SMI_ENTRY *SmiEntry;\r
113 SMI_HANDLER *SmiHandler;\r
114 BOOLEAN SuccessReturn;\r
115 EFI_STATUS Status;\r
116\r
117 Status = EFI_NOT_FOUND;\r
118 SuccessReturn = FALSE;\r
119 if (HandlerType == NULL) {\r
120 //\r
121 // Root SMI handler\r
122 //\r
123 SmiEntry = &mRootSmiEntry;\r
124 } else {\r
125 //\r
126 // Non-root SMI handler\r
127 //\r
128 SmiEntry = SmmCoreFindSmiEntry ((EFI_GUID *) HandlerType, FALSE);\r
129 if (SmiEntry == NULL) {\r
130 //\r
131 // There is no handler registered for this interrupt source\r
132 //\r
133 return Status;\r
134 }\r
135 }\r
136 Head = &SmiEntry->SmiHandlers;\r
137\r
138 for (Link = Head->ForwardLink; Link != Head; Link = Link->ForwardLink) {\r
139 SmiHandler = CR (Link, SMI_HANDLER, Link, SMI_HANDLER_SIGNATURE);\r
140\r
141 Status = SmiHandler->Handler (\r
142 (EFI_HANDLE) SmiHandler,\r
143 Context,\r
144 CommBuffer,\r
145 CommBufferSize\r
146 );\r
147\r
148 switch (Status) {\r
149 case EFI_INTERRUPT_PENDING:\r
150 //\r
151 // If a handler returns EFI_INTERRUPT_PENDING and HandlerType is not NULL then\r
152 // no additional handlers will be processed and EFI_INTERRUPT_PENDING will be returned.\r
153 //\r
154 if (HandlerType != NULL) {\r
155 return EFI_INTERRUPT_PENDING;\r
156 }\r
157 break;\r
158\r
159 case EFI_SUCCESS:\r
160 //\r
161 // If at least one of the handlers returns EFI_SUCCESS then the function will return\r
162 // EFI_SUCCESS. If a handler returns EFI_SUCCESS and HandlerType is not NULL then no\r
163 // additional handlers will be processed.\r
164 //\r
165 if (HandlerType != NULL) {\r
166 return EFI_SUCCESS;\r
167 }\r
168 SuccessReturn = TRUE;\r
169 break;\r
170\r
171 case EFI_WARN_INTERRUPT_SOURCE_QUIESCED:\r
172 //\r
173 // If at least one of the handlers returns EFI_WARN_INTERRUPT_SOURCE_QUIESCED\r
174 // then the function will return EFI_SUCCESS.\r
175 //\r
176 SuccessReturn = TRUE;\r
177 break;\r
178\r
179 case EFI_WARN_INTERRUPT_SOURCE_PENDING:\r
180 //\r
181 // If all the handlers returned EFI_WARN_INTERRUPT_SOURCE_PENDING\r
182 // then EFI_WARN_INTERRUPT_SOURCE_PENDING will be returned.\r
183 //\r
184 break;\r
185\r
186 default:\r
187 //\r
188 // Unexpected status code returned.\r
189 //\r
190 ASSERT (FALSE);\r
191 break;\r
192 }\r
193 }\r
194\r
195 if (SuccessReturn) {\r
196 Status = EFI_SUCCESS;\r
197 }\r
198\r
199 return Status;\r
200}\r
201\r
202/**\r
203 Registers a handler to execute within SMM.\r
204\r
205 @param Handler Handler service funtion pointer.\r
206 @param HandlerType Points to the handler type or NULL for root SMI handlers.\r
207 @param DispatchHandle On return, contains a unique handle which can be used to later unregister the handler function.\r
208\r
209 @retval EFI_SUCCESS Handler register success.\r
210 @retval EFI_INVALID_PARAMETER Handler or DispatchHandle is NULL.\r
211\r
212**/\r
213EFI_STATUS\r
214EFIAPI\r
215SmiHandlerRegister (\r
216 IN EFI_SMM_HANDLER_ENTRY_POINT2 Handler,\r
217 IN CONST EFI_GUID *HandlerType OPTIONAL,\r
218 OUT EFI_HANDLE *DispatchHandle\r
219 )\r
220{\r
221 SMI_HANDLER *SmiHandler;\r
222 SMI_ENTRY *SmiEntry;\r
223 LIST_ENTRY *List;\r
224\r
225 if (Handler == NULL || DispatchHandle == NULL) {\r
226 return EFI_INVALID_PARAMETER;\r
227 }\r
228\r
229 SmiHandler = AllocateZeroPool (sizeof (SMI_HANDLER));\r
230 if (SmiHandler == NULL) {\r
231 return EFI_OUT_OF_RESOURCES;\r
232 }\r
233\r
234 SmiHandler->Signature = SMI_HANDLER_SIGNATURE;\r
235 SmiHandler->Handler = Handler;\r
236 SmiHandler->CallerAddr = (UINTN)RETURN_ADDRESS (0);\r
237\r
238 if (HandlerType == NULL) {\r
239 //\r
240 // This is root SMI handler\r
241 //\r
242 SmiEntry = &mRootSmiEntry;\r
243 } else {\r
244 //\r
245 // None root SMI handler\r
246 //\r
247 SmiEntry = SmmCoreFindSmiEntry ((EFI_GUID *) HandlerType, TRUE);\r
248 if (SmiEntry == NULL) {\r
249 return EFI_OUT_OF_RESOURCES;\r
250 }\r
251 }\r
252 List = &SmiEntry->SmiHandlers;\r
253\r
254 SmiHandler->SmiEntry = SmiEntry;\r
255 InsertTailList (List, &SmiHandler->Link);\r
256\r
257 *DispatchHandle = (EFI_HANDLE) SmiHandler;\r
258\r
259 return EFI_SUCCESS;\r
260}\r
261\r
262/**\r
263 Unregister a handler in SMM.\r
264\r
265 @param DispatchHandle The handle that was specified when the handler was registered.\r
266\r
267 @retval EFI_SUCCESS Handler function was successfully unregistered.\r
268 @retval EFI_INVALID_PARAMETER DispatchHandle does not refer to a valid handle.\r
269\r
270**/\r
271EFI_STATUS\r
272EFIAPI\r
273SmiHandlerUnRegister (\r
274 IN EFI_HANDLE DispatchHandle\r
275 )\r
276{\r
277 SMI_HANDLER *SmiHandler;\r
278 SMI_ENTRY *SmiEntry;\r
279 LIST_ENTRY *EntryLink;\r
280 LIST_ENTRY *HandlerLink;\r
281\r
282 if (DispatchHandle == NULL) {\r
283 return EFI_INVALID_PARAMETER;\r
284 }\r
285\r
286 //\r
287 // Look for it in root SMI handlers\r
288 //\r
289 SmiHandler = NULL;\r
290 for ( HandlerLink = GetFirstNode (&mRootSmiEntry.SmiHandlers)\r
291 ; !IsNull (&mRootSmiEntry.SmiHandlers, HandlerLink) && (SmiHandler != DispatchHandle)\r
292 ; HandlerLink = GetNextNode (&mRootSmiEntry.SmiHandlers, HandlerLink)\r
293 ) {\r
294 SmiHandler = CR (HandlerLink, SMI_HANDLER, Link, SMI_HANDLER_SIGNATURE);\r
295 }\r
296\r
297 //\r
298 // Look for it in non-root SMI handlers\r
299 //\r
300 for ( EntryLink = GetFirstNode (&mSmiEntryList)\r
301 ; !IsNull (&mSmiEntryList, EntryLink) && (SmiHandler != DispatchHandle)\r
302 ; EntryLink = GetNextNode (&mSmiEntryList, EntryLink)\r
303 ) {\r
304 SmiEntry = CR (EntryLink, SMI_ENTRY, AllEntries, SMI_ENTRY_SIGNATURE);\r
305 for ( HandlerLink = GetFirstNode (&SmiEntry->SmiHandlers)\r
306 ; !IsNull (&SmiEntry->SmiHandlers, HandlerLink) && (SmiHandler != DispatchHandle)\r
307 ; HandlerLink = GetNextNode (&SmiEntry->SmiHandlers, HandlerLink)\r
308 ) {\r
309 SmiHandler = CR (HandlerLink, SMI_HANDLER, Link, SMI_HANDLER_SIGNATURE);\r
310 }\r
311 }\r
312\r
313 if (SmiHandler != DispatchHandle) {\r
314 return EFI_INVALID_PARAMETER;\r
315 }\r
316\r
317 SmiEntry = SmiHandler->SmiEntry;\r
318\r
319 RemoveEntryList (&SmiHandler->Link);\r
320 FreePool (SmiHandler);\r
321\r
322 if (SmiEntry == NULL) {\r
323 //\r
324 // This is root SMI handler\r
325 //\r
326 return EFI_SUCCESS;\r
327 }\r
328\r
329 if (IsListEmpty (&SmiEntry->SmiHandlers)) {\r
330 //\r
331 // No handler registered for this interrupt now, remove the SMI_ENTRY\r
332 //\r
333 RemoveEntryList (&SmiEntry->AllEntries);\r
334\r
335 FreePool (SmiEntry);\r
336 }\r
337\r
338 return EFI_SUCCESS;\r
339}\r