]> git.proxmox.com Git - mirror_edk2.git/blame - StandaloneMmPkg/Core/Handle.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / StandaloneMmPkg / Core / Handle.c
CommitLineData
6b46d772
SV
1/** @file\r
2 SMM handle & protocol handling.\r
3\r
4 Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>\r
5 Copyright (c) 2016 - 2018, ARM Limited. All rights reserved.<BR>\r
86094561 6 SPDX-License-Identifier: BSD-2-Clause-Patent\r
6b46d772
SV
7\r
8**/\r
9\r
10#include "StandaloneMmCore.h"\r
11\r
12//\r
13// mProtocolDatabase - A list of all protocols in the system. (simple list for now)\r
14// gHandleList - A list of all the handles in the system\r
15//\r
91415a36
MK
16LIST_ENTRY mProtocolDatabase = INITIALIZE_LIST_HEAD_VARIABLE (mProtocolDatabase);\r
17LIST_ENTRY gHandleList = INITIALIZE_LIST_HEAD_VARIABLE (gHandleList);\r
6b46d772
SV
18\r
19/**\r
20 Check whether a handle is a valid EFI_HANDLE\r
21\r
22 @param UserHandle The handle to check\r
23\r
24 @retval EFI_INVALID_PARAMETER The handle is NULL or not a valid EFI_HANDLE.\r
25 @retval EFI_SUCCESS The handle is valid EFI_HANDLE.\r
26\r
27**/\r
28EFI_STATUS\r
29MmValidateHandle (\r
30 IN EFI_HANDLE UserHandle\r
31 )\r
32{\r
33 IHANDLE *Handle;\r
34\r
35 Handle = (IHANDLE *)UserHandle;\r
36 if (Handle == NULL) {\r
37 return EFI_INVALID_PARAMETER;\r
38 }\r
91415a36 39\r
6b46d772
SV
40 if (Handle->Signature != EFI_HANDLE_SIGNATURE) {\r
41 return EFI_INVALID_PARAMETER;\r
42 }\r
91415a36 43\r
6b46d772
SV
44 return EFI_SUCCESS;\r
45}\r
46\r
47/**\r
48 Finds the protocol entry for the requested protocol.\r
49\r
50 @param Protocol The ID of the protocol\r
51 @param Create Create a new entry if not found\r
52\r
53 @return Protocol entry\r
54\r
55**/\r
56PROTOCOL_ENTRY *\r
57MmFindProtocolEntry (\r
91415a36
MK
58 IN EFI_GUID *Protocol,\r
59 IN BOOLEAN Create\r
6b46d772
SV
60 )\r
61{\r
91415a36
MK
62 LIST_ENTRY *Link;\r
63 PROTOCOL_ENTRY *Item;\r
64 PROTOCOL_ENTRY *ProtEntry;\r
6b46d772
SV
65\r
66 //\r
67 // Search the database for the matching GUID\r
68 //\r
69\r
70 ProtEntry = NULL;\r
71 for (Link = mProtocolDatabase.ForwardLink;\r
72 Link != &mProtocolDatabase;\r
91415a36
MK
73 Link = Link->ForwardLink)\r
74 {\r
6b46d772
SV
75 Item = CR (Link, PROTOCOL_ENTRY, AllEntries, PROTOCOL_ENTRY_SIGNATURE);\r
76 if (CompareGuid (&Item->ProtocolID, Protocol)) {\r
77 //\r
78 // This is the protocol entry\r
79 //\r
80 ProtEntry = Item;\r
81 break;\r
82 }\r
83 }\r
84\r
85 //\r
86 // If the protocol entry was not found and Create is TRUE, then\r
87 // allocate a new entry\r
88 //\r
89 if ((ProtEntry == NULL) && Create) {\r
91415a36 90 ProtEntry = AllocatePool (sizeof (PROTOCOL_ENTRY));\r
6b46d772
SV
91 if (ProtEntry != NULL) {\r
92 //\r
93 // Initialize new protocol entry structure\r
94 //\r
95 ProtEntry->Signature = PROTOCOL_ENTRY_SIGNATURE;\r
96 CopyGuid ((VOID *)&ProtEntry->ProtocolID, Protocol);\r
97 InitializeListHead (&ProtEntry->Protocols);\r
98 InitializeListHead (&ProtEntry->Notify);\r
99\r
100 //\r
101 // Add it to protocol database\r
102 //\r
103 InsertTailList (&mProtocolDatabase, &ProtEntry->AllEntries);\r
104 }\r
105 }\r
91415a36 106\r
6b46d772
SV
107 return ProtEntry;\r
108}\r
109\r
110/**\r
111 Finds the protocol instance for the requested handle and protocol.\r
112 Note: This function doesn't do parameters checking, it's caller's responsibility\r
113 to pass in valid parameters.\r
114\r
115 @param Handle The handle to search the protocol on\r
116 @param Protocol GUID of the protocol\r
117 @param Interface The interface for the protocol being searched\r
118\r
119 @return Protocol instance (NULL: Not found)\r
120\r
121**/\r
122PROTOCOL_INTERFACE *\r
123MmFindProtocolInterface (\r
124 IN IHANDLE *Handle,\r
125 IN EFI_GUID *Protocol,\r
126 IN VOID *Interface\r
127 )\r
128{\r
129 PROTOCOL_INTERFACE *Prot;\r
130 PROTOCOL_ENTRY *ProtEntry;\r
131 LIST_ENTRY *Link;\r
132\r
133 Prot = NULL;\r
134\r
135 //\r
136 // Lookup the protocol entry for this protocol ID\r
137 //\r
138 ProtEntry = MmFindProtocolEntry (Protocol, FALSE);\r
139 if (ProtEntry != NULL) {\r
140 //\r
141 // Look at each protocol interface for any matches\r
142 //\r
91415a36 143 for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link = Link->ForwardLink) {\r
6b46d772
SV
144 //\r
145 // If this protocol interface matches, remove it\r
146 //\r
147 Prot = CR (Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);\r
91415a36 148 if ((Prot->Interface == Interface) && (Prot->Protocol == ProtEntry)) {\r
6b46d772
SV
149 break;\r
150 }\r
91415a36 151\r
6b46d772
SV
152 Prot = NULL;\r
153 }\r
154 }\r
91415a36 155\r
6b46d772
SV
156 return Prot;\r
157}\r
158\r
159/**\r
160 Wrapper function to MmInstallProtocolInterfaceNotify. 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
175MmInstallProtocolInterface (\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 MmInstallProtocolInterfaceNotify (\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
209MmInstallProtocolInterfaceNotify (\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
91415a36 227 if ((UserHandle == NULL) || (Protocol == NULL)) {\r
6b46d772
SV
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, "MmInstallProtocolInterface: %g %p\n", Protocol, Interface));\r
239\r
240 Status = EFI_OUT_OF_RESOURCES;\r
91415a36 241 Prot = NULL;\r
6b46d772
SV
242 Handle = NULL;\r
243\r
244 if (*UserHandle != NULL) {\r
245 Status = MmHandleProtocol (*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 = MmFindProtocolEntry (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 = MmValidateHandle (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 (MmFindProtocolInterface (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
91415a36
MK
306 Prot->Handle = Handle;\r
307 Prot->Protocol = ProtEntry;\r
6b46d772
SV
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 MmNotifyProtocol (Prot);\r
327 }\r
91415a36 328\r
6b46d772
SV
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
344 }\r
91415a36 345\r
6b46d772
SV
346 return Status;\r
347}\r
348\r
349/**\r
350 Uninstalls all instances of a protocol:interfacer from a handle.\r
351 If the last protocol interface is remove from the handle, the\r
352 handle is freed.\r
353\r
354 @param UserHandle The handle to remove the protocol handler from\r
355 @param Protocol The protocol, of protocol:interface, to remove\r
356 @param Interface The interface, of protocol:interface, to remove\r
357\r
358 @retval EFI_INVALID_PARAMETER Protocol is NULL.\r
359 @retval EFI_SUCCESS Protocol interface successfully uninstalled.\r
360\r
361**/\r
362EFI_STATUS\r
363EFIAPI\r
364MmUninstallProtocolInterface (\r
365 IN EFI_HANDLE UserHandle,\r
366 IN EFI_GUID *Protocol,\r
367 IN VOID *Interface\r
368 )\r
369{\r
370 EFI_STATUS Status;\r
371 IHANDLE *Handle;\r
372 PROTOCOL_INTERFACE *Prot;\r
373\r
374 //\r
375 // Check that Protocol is valid\r
376 //\r
377 if (Protocol == NULL) {\r
378 return EFI_INVALID_PARAMETER;\r
379 }\r
380\r
381 //\r
382 // Check that UserHandle is a valid handle\r
383 //\r
384 Status = MmValidateHandle (UserHandle);\r
385 if (EFI_ERROR (Status)) {\r
386 return Status;\r
387 }\r
388\r
389 //\r
390 // Check that Protocol exists on UserHandle, and Interface matches the interface in the database\r
391 //\r
392 Prot = MmFindProtocolInterface (UserHandle, Protocol, Interface);\r
393 if (Prot == NULL) {\r
394 return EFI_NOT_FOUND;\r
395 }\r
396\r
397 //\r
398 // Remove the protocol interface from the protocol\r
399 //\r
400 Status = EFI_NOT_FOUND;\r
401 Handle = (IHANDLE *)UserHandle;\r
402 Prot = MmRemoveInterfaceFromProtocol (Handle, Protocol, Interface);\r
403\r
404 if (Prot != NULL) {\r
405 //\r
406 // Remove the protocol interface from the handle\r
407 //\r
408 RemoveEntryList (&Prot->Link);\r
409\r
410 //\r
411 // Free the memory\r
412 //\r
413 Prot->Signature = 0;\r
414 FreePool (Prot);\r
415 Status = EFI_SUCCESS;\r
416 }\r
417\r
418 //\r
419 // If there are no more handlers for the handle, free the handle\r
420 //\r
421 if (IsListEmpty (&Handle->Protocols)) {\r
422 Handle->Signature = 0;\r
423 RemoveEntryList (&Handle->AllHandles);\r
424 FreePool (Handle);\r
425 }\r
91415a36 426\r
6b46d772
SV
427 return Status;\r
428}\r
429\r
430/**\r
431 Locate a certain GUID protocol interface in a Handle's protocols.\r
432\r
433 @param UserHandle The handle to obtain the protocol interface on\r
434 @param Protocol The GUID of the protocol\r
435\r
436 @return The requested protocol interface for the handle\r
437\r
438**/\r
439PROTOCOL_INTERFACE *\r
440MmGetProtocolInterface (\r
441 IN EFI_HANDLE UserHandle,\r
442 IN EFI_GUID *Protocol\r
443 )\r
444{\r
445 EFI_STATUS Status;\r
446 PROTOCOL_ENTRY *ProtEntry;\r
447 PROTOCOL_INTERFACE *Prot;\r
448 IHANDLE *Handle;\r
449 LIST_ENTRY *Link;\r
450\r
451 Status = MmValidateHandle (UserHandle);\r
452 if (EFI_ERROR (Status)) {\r
453 return NULL;\r
454 }\r
455\r
456 Handle = (IHANDLE *)UserHandle;\r
457\r
458 //\r
459 // Look at each protocol interface for a match\r
460 //\r
461 for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link = Link->ForwardLink) {\r
91415a36 462 Prot = CR (Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);\r
6b46d772
SV
463 ProtEntry = Prot->Protocol;\r
464 if (CompareGuid (&ProtEntry->ProtocolID, Protocol)) {\r
465 return Prot;\r
466 }\r
467 }\r
91415a36 468\r
6b46d772
SV
469 return NULL;\r
470}\r
471\r
472/**\r
473 Queries a handle to determine if it supports a specified protocol.\r
474\r
475 @param UserHandle The handle being queried.\r
476 @param Protocol The published unique identifier of the protocol.\r
477 @param Interface Supplies the address where a pointer to the\r
478 corresponding Protocol Interface is returned.\r
479\r
480 @retval EFI_SUCCESS The interface information for the specified protocol was returned.\r
481 @retval EFI_UNSUPPORTED The device does not support the specified protocol.\r
482 @retval EFI_INVALID_PARAMETER Handle is not a valid EFI_HANDLE..\r
483 @retval EFI_INVALID_PARAMETER Protocol is NULL.\r
484 @retval EFI_INVALID_PARAMETER Interface is NULL.\r
485\r
486**/\r
487EFI_STATUS\r
488EFIAPI\r
489MmHandleProtocol (\r
490 IN EFI_HANDLE UserHandle,\r
491 IN EFI_GUID *Protocol,\r
492 OUT VOID **Interface\r
493 )\r
494{\r
495 EFI_STATUS Status;\r
496 PROTOCOL_INTERFACE *Prot;\r
497\r
498 //\r
499 // Check for invalid Protocol\r
500 //\r
501 if (Protocol == NULL) {\r
502 return EFI_INVALID_PARAMETER;\r
503 }\r
504\r
505 //\r
506 // Check for invalid Interface\r
507 //\r
508 if (Interface == NULL) {\r
509 return EFI_INVALID_PARAMETER;\r
510 } else {\r
511 *Interface = NULL;\r
512 }\r
513\r
514 //\r
515 // Check for invalid UserHandle\r
516 //\r
517 Status = MmValidateHandle (UserHandle);\r
518 if (EFI_ERROR (Status)) {\r
519 return Status;\r
520 }\r
521\r
522 //\r
523 // Look at each protocol interface for a match\r
524 //\r
525 Prot = MmGetProtocolInterface (UserHandle, Protocol);\r
526 if (Prot == NULL) {\r
527 return EFI_UNSUPPORTED;\r
528 }\r
529\r
530 //\r
531 // This is the protocol interface entry for this protocol\r
532 //\r
533 *Interface = Prot->Interface;\r
534\r
535 return EFI_SUCCESS;\r
536}\r