]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Core/PiSmmCore/Handle.c
Clean up DEC files:
[mirror_edk2.git] / MdeModulePkg / Core / PiSmmCore / Handle.c
CommitLineData
e42e9404 1/** @file\r
2 SMM handle & protocol handling.\r
3\r
cd5ebaa0 4 Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>\r
e42e9404 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
17//\r
18// mProtocolDatabase - A list of all protocols in the system. (simple list for now)\r
19// gHandleList - A list of all the handles in the system\r
20//\r
21LIST_ENTRY mProtocolDatabase = INITIALIZE_LIST_HEAD_VARIABLE (mProtocolDatabase);\r
22LIST_ENTRY gHandleList = INITIALIZE_LIST_HEAD_VARIABLE (gHandleList);\r
23\r
24/**\r
25 Check whether a handle is a valid EFI_HANDLE\r
26\r
27 @param UserHandle The handle to check\r
28\r
29 @retval EFI_INVALID_PARAMETER The handle is NULL or not a valid EFI_HANDLE.\r
30 @retval EFI_SUCCESS The handle is valid EFI_HANDLE.\r
31\r
32**/\r
33EFI_STATUS\r
34SmmValidateHandle (\r
35 IN EFI_HANDLE UserHandle\r
36 )\r
37{\r
38 IHANDLE *Handle;\r
39\r
40 Handle = (IHANDLE *)UserHandle;\r
41 if (Handle == NULL) {\r
42 return EFI_INVALID_PARAMETER;\r
43 }\r
44 if (Handle->Signature != EFI_HANDLE_SIGNATURE) {\r
45 return EFI_INVALID_PARAMETER;\r
46 }\r
47 return EFI_SUCCESS;\r
48}\r
49\r
50/**\r
51 Finds the protocol entry for the requested protocol.\r
52\r
53 @param Protocol The ID of the protocol\r
54 @param Create Create a new entry if not found\r
55\r
56 @return Protocol entry\r
57\r
58**/\r
59PROTOCOL_ENTRY *\r
60SmmFindProtocolEntry (\r
61 IN EFI_GUID *Protocol,\r
62 IN BOOLEAN Create\r
63 )\r
64{\r
65 LIST_ENTRY *Link;\r
66 PROTOCOL_ENTRY *Item;\r
67 PROTOCOL_ENTRY *ProtEntry;\r
68\r
69 //\r
70 // Search the database for the matching GUID\r
71 //\r
72\r
73 ProtEntry = NULL;\r
74 for (Link = mProtocolDatabase.ForwardLink;\r
75 Link != &mProtocolDatabase;\r
76 Link = Link->ForwardLink) {\r
77\r
78 Item = CR(Link, PROTOCOL_ENTRY, AllEntries, PROTOCOL_ENTRY_SIGNATURE);\r
79 if (CompareGuid (&Item->ProtocolID, Protocol)) {\r
80 //\r
81 // This is the protocol entry\r
82 //\r
83 ProtEntry = Item;\r
84 break;\r
85 }\r
86 }\r
87\r
88 //\r
89 // If the protocol entry was not found and Create is TRUE, then\r
90 // allocate a new entry\r
91 //\r
92 if ((ProtEntry == NULL) && Create) {\r
93 ProtEntry = AllocatePool (sizeof(PROTOCOL_ENTRY));\r
94 if (ProtEntry != NULL) {\r
95 //\r
96 // Initialize new protocol entry structure\r
97 //\r
98 ProtEntry->Signature = PROTOCOL_ENTRY_SIGNATURE;\r
99 CopyGuid ((VOID *)&ProtEntry->ProtocolID, Protocol);\r
100 InitializeListHead (&ProtEntry->Protocols);\r
101 InitializeListHead (&ProtEntry->Notify);\r
102\r
103 //\r
104 // Add it to protocol database\r
105 //\r
106 InsertTailList (&mProtocolDatabase, &ProtEntry->AllEntries);\r
107 }\r
108 }\r
109 return ProtEntry;\r
110}\r
111\r
112/**\r
113 Finds the protocol instance for the requested handle and protocol.\r
114 Note: This function doesn't do parameters checking, it's caller's responsibility\r
115 to pass in valid parameters.\r
116\r
117 @param Handle The handle to search the protocol on\r
118 @param Protocol GUID of the protocol\r
119 @param Interface The interface for the protocol being searched\r
120\r
121 @return Protocol instance (NULL: Not found)\r
122\r
123**/\r
124PROTOCOL_INTERFACE *\r
125SmmFindProtocolInterface (\r
126 IN IHANDLE *Handle,\r
127 IN EFI_GUID *Protocol,\r
128 IN VOID *Interface\r
129 )\r
130{\r
131 PROTOCOL_INTERFACE *Prot;\r
132 PROTOCOL_ENTRY *ProtEntry;\r
133 LIST_ENTRY *Link;\r
134\r
135 Prot = NULL;\r
136\r
137 //\r
138 // Lookup the protocol entry for this protocol ID\r
139 //\r
140 ProtEntry = SmmFindProtocolEntry (Protocol, FALSE);\r
141 if (ProtEntry != NULL) {\r
142 //\r
143 // Look at each protocol interface for any matches\r
144 //\r
145 for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link=Link->ForwardLink) {\r
146 //\r
147 // If this protocol interface matches, remove it\r
148 //\r
149 Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);\r
150 if (Prot->Interface == Interface && Prot->Protocol == ProtEntry) {\r
151 break;\r
152 }\r
153 Prot = NULL;\r
154 }\r
155 }\r
156 return Prot;\r
157}\r
158\r
159/**\r
160 Wrapper function to SmmInstallProtocolInterfaceNotify. This is the public API which\r
161 Calls the private one which contains a BOOLEAN parameter for notifications\r
162\r
163 @param UserHandle The handle to install the protocol handler on,\r
164 or NULL if a new handle is to be allocated\r
165 @param Protocol The protocol to add to the handle\r
166 @param InterfaceType Indicates whether Interface is supplied in\r
167 native form.\r
168 @param Interface The interface for the protocol being added\r
169\r
170 @return Status code\r
171\r
172**/\r
173EFI_STATUS\r
174EFIAPI\r
175SmmInstallProtocolInterface (\r
176 IN OUT EFI_HANDLE *UserHandle,\r
177 IN EFI_GUID *Protocol,\r
178 IN EFI_INTERFACE_TYPE InterfaceType,\r
179 IN VOID *Interface\r
180 )\r
181{\r
182 return SmmInstallProtocolInterfaceNotify (\r
183 UserHandle,\r
184 Protocol,\r
185 InterfaceType,\r
186 Interface,\r
187 TRUE\r
188 );\r
189}\r
190\r
191/**\r
192 Installs a protocol interface into the boot services environment.\r
193\r
194 @param UserHandle The handle to install the protocol handler on,\r
195 or NULL if a new handle is to be allocated\r
196 @param Protocol The protocol to add to the handle\r
197 @param InterfaceType Indicates whether Interface is supplied in\r
198 native form.\r
199 @param Interface The interface for the protocol being added\r
200 @param Notify indicates whether notify the notification list\r
201 for this protocol\r
202\r
203 @retval EFI_INVALID_PARAMETER Invalid parameter\r
204 @retval EFI_OUT_OF_RESOURCES No enough buffer to allocate\r
205 @retval EFI_SUCCESS Protocol interface successfully installed\r
206\r
207**/\r
208EFI_STATUS\r
209SmmInstallProtocolInterfaceNotify (\r
210 IN OUT EFI_HANDLE *UserHandle,\r
211 IN EFI_GUID *Protocol,\r
212 IN EFI_INTERFACE_TYPE InterfaceType,\r
213 IN VOID *Interface,\r
214 IN BOOLEAN Notify\r
215 )\r
216{\r
217 PROTOCOL_INTERFACE *Prot;\r
218 PROTOCOL_ENTRY *ProtEntry;\r
219 IHANDLE *Handle;\r
220 EFI_STATUS Status;\r
221 VOID *ExistingInterface;\r
222\r
223 //\r
224 // returns EFI_INVALID_PARAMETER if InterfaceType is invalid.\r
225 // Also added check for invalid UserHandle and Protocol pointers.\r
226 //\r
227 if (UserHandle == NULL || Protocol == NULL) {\r
228 return EFI_INVALID_PARAMETER;\r
229 }\r
230\r
231 if (InterfaceType != EFI_NATIVE_INTERFACE) {\r
232 return EFI_INVALID_PARAMETER;\r
233 }\r
234\r
235 //\r
236 // Print debug message\r
237 //\r
238 DEBUG((DEBUG_LOAD | DEBUG_INFO, "SmmInstallProtocolInterface: %g %p\n", Protocol, Interface));\r
239\r
240 Status = EFI_OUT_OF_RESOURCES;\r
241 Prot = NULL;\r
242 Handle = NULL;\r
243\r
244 if (*UserHandle != NULL) {\r
245 Status = SmmHandleProtocol (*UserHandle, Protocol, (VOID **)&ExistingInterface);\r
246 if (!EFI_ERROR (Status)) {\r
247 return EFI_INVALID_PARAMETER;\r
248 }\r
249 }\r
250\r
251 //\r
252 // Lookup the Protocol Entry for the requested protocol\r
253 //\r
254 ProtEntry = SmmFindProtocolEntry (Protocol, TRUE);\r
255 if (ProtEntry == NULL) {\r
256 goto Done;\r
257 }\r
258\r
259 //\r
260 // Allocate a new protocol interface structure\r
261 //\r
262 Prot = AllocateZeroPool (sizeof(PROTOCOL_INTERFACE));\r
263 if (Prot == NULL) {\r
264 Status = EFI_OUT_OF_RESOURCES;\r
265 goto Done;\r
266 }\r
267\r
268 //\r
269 // If caller didn't supply a handle, allocate a new one\r
270 //\r
271 Handle = (IHANDLE *)*UserHandle;\r
272 if (Handle == NULL) {\r
273 Handle = AllocateZeroPool (sizeof(IHANDLE));\r
274 if (Handle == NULL) {\r
275 Status = EFI_OUT_OF_RESOURCES;\r
276 goto Done;\r
277 }\r
278\r
279 //\r
280 // Initialize new handler structure\r
281 //\r
282 Handle->Signature = EFI_HANDLE_SIGNATURE;\r
283 InitializeListHead (&Handle->Protocols);\r
284\r
285 //\r
286 // Add this handle to the list global list of all handles\r
287 // in the system\r
288 //\r
289 InsertTailList (&gHandleList, &Handle->AllHandles);\r
290 }\r
291\r
292 Status = SmmValidateHandle (Handle);\r
293 if (EFI_ERROR (Status)) {\r
294 goto Done;\r
295 }\r
296\r
297 //\r
298 // Each interface that is added must be unique\r
299 //\r
300 ASSERT (SmmFindProtocolInterface (Handle, Protocol, Interface) == NULL);\r
301\r
302 //\r
303 // Initialize the protocol interface structure\r
304 //\r
305 Prot->Signature = PROTOCOL_INTERFACE_SIGNATURE;\r
306 Prot->Handle = Handle;\r
307 Prot->Protocol = ProtEntry;\r
308 Prot->Interface = Interface;\r
309\r
310 //\r
311 // Add this protocol interface to the head of the supported\r
312 // protocol list for this handle\r
313 //\r
314 InsertHeadList (&Handle->Protocols, &Prot->Link);\r
315\r
316 //\r
317 // Add this protocol interface to the tail of the\r
318 // protocol entry\r
319 //\r
320 InsertTailList (&ProtEntry->Protocols, &Prot->ByProtocol);\r
321\r
322 //\r
323 // Notify the notification list for this protocol\r
324 //\r
325 if (Notify) {\r
326 SmmNotifyProtocol (Prot);\r
327 }\r
328 Status = EFI_SUCCESS;\r
329\r
330Done:\r
331 if (!EFI_ERROR (Status)) {\r
332 //\r
333 // Return the new handle back to the caller\r
334 //\r
335 *UserHandle = Handle;\r
336 } else {\r
337 //\r
338 // There was an error, clean up\r
339 //\r
340 if (Prot != NULL) {\r
341 FreePool (Prot);\r
342 }\r
343 }\r
344 return Status;\r
345}\r
346\r
347/**\r
348 Uninstalls all instances of a protocol:interfacer from a handle.\r
349 If the last protocol interface is remove from the handle, the\r
350 handle is freed.\r
351\r
352 @param UserHandle The handle to remove the protocol handler from\r
353 @param Protocol The protocol, of protocol:interface, to remove\r
354 @param Interface The interface, of protocol:interface, to remove\r
355\r
356 @retval EFI_INVALID_PARAMETER Protocol is NULL.\r
357 @retval EFI_SUCCESS Protocol interface successfully uninstalled.\r
358\r
359**/\r
360EFI_STATUS\r
361EFIAPI\r
362SmmUninstallProtocolInterface (\r
363 IN EFI_HANDLE UserHandle,\r
364 IN EFI_GUID *Protocol,\r
365 IN VOID *Interface\r
366 )\r
367{\r
368 EFI_STATUS Status;\r
369 IHANDLE *Handle;\r
370 PROTOCOL_INTERFACE *Prot;\r
371\r
372 //\r
373 // Check that Protocol is valid\r
374 //\r
375 if (Protocol == NULL) {\r
376 return EFI_INVALID_PARAMETER;\r
377 }\r
378\r
379 //\r
380 // Check that UserHandle is a valid handle\r
381 //\r
382 Status = SmmValidateHandle (UserHandle);\r
383 if (EFI_ERROR (Status)) {\r
384 return Status;\r
385 }\r
386\r
387 //\r
388 // Check that Protocol exists on UserHandle, and Interface matches the interface in the database\r
389 //\r
390 Prot = SmmFindProtocolInterface (UserHandle, Protocol, Interface);\r
391 if (Prot == NULL) {\r
392 return EFI_NOT_FOUND;\r
393 }\r
394\r
395 //\r
396 // Remove the protocol interface from the protocol\r
397 //\r
398 Status = EFI_NOT_FOUND;\r
399 Handle = (IHANDLE *)UserHandle;\r
400 Prot = SmmRemoveInterfaceFromProtocol (Handle, Protocol, Interface);\r
401\r
402 if (Prot != NULL) {\r
403 //\r
404 // Remove the protocol interface from the handle\r
405 //\r
406 RemoveEntryList (&Prot->Link);\r
407\r
408 //\r
409 // Free the memory\r
410 //\r
411 Prot->Signature = 0;\r
412 FreePool (Prot);\r
413 Status = EFI_SUCCESS;\r
414 }\r
415\r
416 //\r
417 // If there are no more handlers for the handle, free the handle\r
418 //\r
419 if (IsListEmpty (&Handle->Protocols)) {\r
420 Handle->Signature = 0;\r
421 RemoveEntryList (&Handle->AllHandles);\r
422 FreePool (Handle);\r
423 }\r
424 return Status;\r
425}\r
426\r
427/**\r
428 Locate a certain GUID protocol interface in a Handle's protocols.\r
429\r
430 @param UserHandle The handle to obtain the protocol interface on\r
431 @param Protocol The GUID of the protocol\r
432\r
433 @return The requested protocol interface for the handle\r
434\r
435**/\r
436PROTOCOL_INTERFACE *\r
437SmmGetProtocolInterface (\r
438 IN EFI_HANDLE UserHandle,\r
439 IN EFI_GUID *Protocol\r
440 )\r
441{\r
442 EFI_STATUS Status;\r
443 PROTOCOL_ENTRY *ProtEntry;\r
444 PROTOCOL_INTERFACE *Prot;\r
445 IHANDLE *Handle;\r
446 LIST_ENTRY *Link;\r
447\r
448 Status = SmmValidateHandle (UserHandle);\r
449 if (EFI_ERROR (Status)) {\r
450 return NULL;\r
451 }\r
452\r
453 Handle = (IHANDLE *)UserHandle;\r
454\r
455 //\r
456 // Look at each protocol interface for a match\r
457 //\r
458 for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link = Link->ForwardLink) {\r
459 Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);\r
460 ProtEntry = Prot->Protocol;\r
461 if (CompareGuid (&ProtEntry->ProtocolID, Protocol)) {\r
462 return Prot;\r
463 }\r
464 }\r
465 return NULL;\r
466}\r
467\r
468/**\r
469 Queries a handle to determine if it supports a specified protocol.\r
470\r
471 @param UserHandle The handle being queried.\r
472 @param Protocol The published unique identifier of the protocol.\r
473 @param Interface Supplies the address where a pointer to the\r
474 corresponding Protocol Interface is returned.\r
475\r
476 @retval EFI_SUCCESS The interface information for the specified protocol was returned.\r
477 @retval EFI_UNSUPPORTED The device does not support the specified protocol.\r
478 @retval EFI_INVALID_PARAMETER Handle is not a valid EFI_HANDLE..\r
479 @retval EFI_INVALID_PARAMETER Protocol is NULL.\r
480 @retval EFI_INVALID_PARAMETER Interface is NULL.\r
481\r
482**/\r
483EFI_STATUS\r
484EFIAPI\r
485SmmHandleProtocol (\r
486 IN EFI_HANDLE UserHandle,\r
487 IN EFI_GUID *Protocol,\r
488 OUT VOID **Interface\r
489 )\r
490{\r
491 EFI_STATUS Status;\r
492 PROTOCOL_INTERFACE *Prot;\r
493\r
494 //\r
495 // Check for invalid Protocol\r
496 //\r
497 if (Protocol == NULL) {\r
498 return EFI_INVALID_PARAMETER;\r
499 }\r
500\r
501 //\r
502 // Check for invalid Interface\r
503 //\r
504 if (Interface == NULL) {\r
505 return EFI_INVALID_PARAMETER;\r
506 } else {\r
507 *Interface = NULL;\r
508 }\r
509\r
510 //\r
511 // Check for invalid UserHandle\r
512 //\r
513 Status = SmmValidateHandle (UserHandle);\r
514 if (EFI_ERROR (Status)) {\r
515 return Status;\r
516 }\r
517\r
518 //\r
519 // Look at each protocol interface for a match\r
520 //\r
521 Prot = SmmGetProtocolInterface (UserHandle, Protocol);\r
522 if (Prot == NULL) {\r
523 return EFI_UNSUPPORTED;\r
524 }\r
525\r
526 //\r
527 // This is the protocol interface entry for this protocol\r
528 //\r
529 *Interface = Prot->Interface;\r
530\r
531 return EFI_SUCCESS;\r
532}\r