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