2 SMM handle & protocol handling.
4 Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
5 Copyright (c) 2016 - 2018, ARM Limited. All rights reserved.<BR>
6 SPDX-License-Identifier: BSD-2-Clause-Patent
10 #include "StandaloneMmCore.h"
13 // mProtocolDatabase - A list of all protocols in the system. (simple list for now)
14 // gHandleList - A list of all the handles in the system
16 LIST_ENTRY mProtocolDatabase
= INITIALIZE_LIST_HEAD_VARIABLE (mProtocolDatabase
);
17 LIST_ENTRY gHandleList
= INITIALIZE_LIST_HEAD_VARIABLE (gHandleList
);
20 Check whether a handle is a valid EFI_HANDLE
22 @param UserHandle The handle to check
24 @retval EFI_INVALID_PARAMETER The handle is NULL or not a valid EFI_HANDLE.
25 @retval EFI_SUCCESS The handle is valid EFI_HANDLE.
30 IN EFI_HANDLE UserHandle
35 Handle
= (IHANDLE
*)UserHandle
;
37 return EFI_INVALID_PARAMETER
;
39 if (Handle
->Signature
!= EFI_HANDLE_SIGNATURE
) {
40 return EFI_INVALID_PARAMETER
;
46 Finds the protocol entry for the requested protocol.
48 @param Protocol The ID of the protocol
49 @param Create Create a new entry if not found
51 @return Protocol entry
56 IN EFI_GUID
*Protocol
,
62 PROTOCOL_ENTRY
*ProtEntry
;
65 // Search the database for the matching GUID
69 for (Link
= mProtocolDatabase
.ForwardLink
;
70 Link
!= &mProtocolDatabase
;
71 Link
= Link
->ForwardLink
) {
73 Item
= CR (Link
, PROTOCOL_ENTRY
, AllEntries
, PROTOCOL_ENTRY_SIGNATURE
);
74 if (CompareGuid (&Item
->ProtocolID
, Protocol
)) {
76 // This is the protocol entry
84 // If the protocol entry was not found and Create is TRUE, then
85 // allocate a new entry
87 if ((ProtEntry
== NULL
) && Create
) {
88 ProtEntry
= AllocatePool (sizeof(PROTOCOL_ENTRY
));
89 if (ProtEntry
!= NULL
) {
91 // Initialize new protocol entry structure
93 ProtEntry
->Signature
= PROTOCOL_ENTRY_SIGNATURE
;
94 CopyGuid ((VOID
*)&ProtEntry
->ProtocolID
, Protocol
);
95 InitializeListHead (&ProtEntry
->Protocols
);
96 InitializeListHead (&ProtEntry
->Notify
);
99 // Add it to protocol database
101 InsertTailList (&mProtocolDatabase
, &ProtEntry
->AllEntries
);
108 Finds the protocol instance for the requested handle and protocol.
109 Note: This function doesn't do parameters checking, it's caller's responsibility
110 to pass in valid parameters.
112 @param Handle The handle to search the protocol on
113 @param Protocol GUID of the protocol
114 @param Interface The interface for the protocol being searched
116 @return Protocol instance (NULL: Not found)
120 MmFindProtocolInterface (
122 IN EFI_GUID
*Protocol
,
126 PROTOCOL_INTERFACE
*Prot
;
127 PROTOCOL_ENTRY
*ProtEntry
;
133 // Lookup the protocol entry for this protocol ID
135 ProtEntry
= MmFindProtocolEntry (Protocol
, FALSE
);
136 if (ProtEntry
!= NULL
) {
138 // Look at each protocol interface for any matches
140 for (Link
= Handle
->Protocols
.ForwardLink
; Link
!= &Handle
->Protocols
; Link
=Link
->ForwardLink
) {
142 // If this protocol interface matches, remove it
144 Prot
= CR (Link
, PROTOCOL_INTERFACE
, Link
, PROTOCOL_INTERFACE_SIGNATURE
);
145 if (Prot
->Interface
== Interface
&& Prot
->Protocol
== ProtEntry
) {
155 Wrapper function to MmInstallProtocolInterfaceNotify. This is the public API which
156 Calls the private one which contains a BOOLEAN parameter for notifications
158 @param UserHandle The handle to install the protocol handler on,
159 or NULL if a new handle is to be allocated
160 @param Protocol The protocol to add to the handle
161 @param InterfaceType Indicates whether Interface is supplied in
163 @param Interface The interface for the protocol being added
170 MmInstallProtocolInterface (
171 IN OUT EFI_HANDLE
*UserHandle
,
172 IN EFI_GUID
*Protocol
,
173 IN EFI_INTERFACE_TYPE InterfaceType
,
177 return MmInstallProtocolInterfaceNotify (
187 Installs a protocol interface into the boot services environment.
189 @param UserHandle The handle to install the protocol handler on,
190 or NULL if a new handle is to be allocated
191 @param Protocol The protocol to add to the handle
192 @param InterfaceType Indicates whether Interface is supplied in
194 @param Interface The interface for the protocol being added
195 @param Notify indicates whether notify the notification list
198 @retval EFI_INVALID_PARAMETER Invalid parameter
199 @retval EFI_OUT_OF_RESOURCES No enough buffer to allocate
200 @retval EFI_SUCCESS Protocol interface successfully installed
204 MmInstallProtocolInterfaceNotify (
205 IN OUT EFI_HANDLE
*UserHandle
,
206 IN EFI_GUID
*Protocol
,
207 IN EFI_INTERFACE_TYPE InterfaceType
,
212 PROTOCOL_INTERFACE
*Prot
;
213 PROTOCOL_ENTRY
*ProtEntry
;
216 VOID
*ExistingInterface
;
219 // returns EFI_INVALID_PARAMETER if InterfaceType is invalid.
220 // Also added check for invalid UserHandle and Protocol pointers.
222 if (UserHandle
== NULL
|| Protocol
== NULL
) {
223 return EFI_INVALID_PARAMETER
;
226 if (InterfaceType
!= EFI_NATIVE_INTERFACE
) {
227 return EFI_INVALID_PARAMETER
;
231 // Print debug message
233 DEBUG ((DEBUG_LOAD
| DEBUG_INFO
, "MmInstallProtocolInterface: %g %p\n", Protocol
, Interface
));
235 Status
= EFI_OUT_OF_RESOURCES
;
239 if (*UserHandle
!= NULL
) {
240 Status
= MmHandleProtocol (*UserHandle
, Protocol
, (VOID
**)&ExistingInterface
);
241 if (!EFI_ERROR (Status
)) {
242 return EFI_INVALID_PARAMETER
;
247 // Lookup the Protocol Entry for the requested protocol
249 ProtEntry
= MmFindProtocolEntry (Protocol
, TRUE
);
250 if (ProtEntry
== NULL
) {
255 // Allocate a new protocol interface structure
257 Prot
= AllocateZeroPool (sizeof (PROTOCOL_INTERFACE
));
259 Status
= EFI_OUT_OF_RESOURCES
;
264 // If caller didn't supply a handle, allocate a new one
266 Handle
= (IHANDLE
*)*UserHandle
;
267 if (Handle
== NULL
) {
268 Handle
= AllocateZeroPool (sizeof (IHANDLE
));
269 if (Handle
== NULL
) {
270 Status
= EFI_OUT_OF_RESOURCES
;
275 // Initialize new handler structure
277 Handle
->Signature
= EFI_HANDLE_SIGNATURE
;
278 InitializeListHead (&Handle
->Protocols
);
281 // Add this handle to the list global list of all handles
284 InsertTailList (&gHandleList
, &Handle
->AllHandles
);
287 Status
= MmValidateHandle (Handle
);
288 if (EFI_ERROR (Status
)) {
293 // Each interface that is added must be unique
295 ASSERT (MmFindProtocolInterface (Handle
, Protocol
, Interface
) == NULL
);
298 // Initialize the protocol interface structure
300 Prot
->Signature
= PROTOCOL_INTERFACE_SIGNATURE
;
301 Prot
->Handle
= Handle
;
302 Prot
->Protocol
= ProtEntry
;
303 Prot
->Interface
= Interface
;
306 // Add this protocol interface to the head of the supported
307 // protocol list for this handle
309 InsertHeadList (&Handle
->Protocols
, &Prot
->Link
);
312 // Add this protocol interface to the tail of the
315 InsertTailList (&ProtEntry
->Protocols
, &Prot
->ByProtocol
);
318 // Notify the notification list for this protocol
321 MmNotifyProtocol (Prot
);
323 Status
= EFI_SUCCESS
;
326 if (!EFI_ERROR (Status
)) {
328 // Return the new handle back to the caller
330 *UserHandle
= Handle
;
333 // There was an error, clean up
343 Uninstalls all instances of a protocol:interfacer from a handle.
344 If the last protocol interface is remove from the handle, the
347 @param UserHandle The handle to remove the protocol handler from
348 @param Protocol The protocol, of protocol:interface, to remove
349 @param Interface The interface, of protocol:interface, to remove
351 @retval EFI_INVALID_PARAMETER Protocol is NULL.
352 @retval EFI_SUCCESS Protocol interface successfully uninstalled.
357 MmUninstallProtocolInterface (
358 IN EFI_HANDLE UserHandle
,
359 IN EFI_GUID
*Protocol
,
365 PROTOCOL_INTERFACE
*Prot
;
368 // Check that Protocol is valid
370 if (Protocol
== NULL
) {
371 return EFI_INVALID_PARAMETER
;
375 // Check that UserHandle is a valid handle
377 Status
= MmValidateHandle (UserHandle
);
378 if (EFI_ERROR (Status
)) {
383 // Check that Protocol exists on UserHandle, and Interface matches the interface in the database
385 Prot
= MmFindProtocolInterface (UserHandle
, Protocol
, Interface
);
387 return EFI_NOT_FOUND
;
391 // Remove the protocol interface from the protocol
393 Status
= EFI_NOT_FOUND
;
394 Handle
= (IHANDLE
*)UserHandle
;
395 Prot
= MmRemoveInterfaceFromProtocol (Handle
, Protocol
, Interface
);
399 // Remove the protocol interface from the handle
401 RemoveEntryList (&Prot
->Link
);
408 Status
= EFI_SUCCESS
;
412 // If there are no more handlers for the handle, free the handle
414 if (IsListEmpty (&Handle
->Protocols
)) {
415 Handle
->Signature
= 0;
416 RemoveEntryList (&Handle
->AllHandles
);
423 Locate a certain GUID protocol interface in a Handle's protocols.
425 @param UserHandle The handle to obtain the protocol interface on
426 @param Protocol The GUID of the protocol
428 @return The requested protocol interface for the handle
432 MmGetProtocolInterface (
433 IN EFI_HANDLE UserHandle
,
434 IN EFI_GUID
*Protocol
438 PROTOCOL_ENTRY
*ProtEntry
;
439 PROTOCOL_INTERFACE
*Prot
;
443 Status
= MmValidateHandle (UserHandle
);
444 if (EFI_ERROR (Status
)) {
448 Handle
= (IHANDLE
*)UserHandle
;
451 // Look at each protocol interface for a match
453 for (Link
= Handle
->Protocols
.ForwardLink
; Link
!= &Handle
->Protocols
; Link
= Link
->ForwardLink
) {
454 Prot
= CR (Link
, PROTOCOL_INTERFACE
, Link
, PROTOCOL_INTERFACE_SIGNATURE
);
455 ProtEntry
= Prot
->Protocol
;
456 if (CompareGuid (&ProtEntry
->ProtocolID
, Protocol
)) {
464 Queries a handle to determine if it supports a specified protocol.
466 @param UserHandle The handle being queried.
467 @param Protocol The published unique identifier of the protocol.
468 @param Interface Supplies the address where a pointer to the
469 corresponding Protocol Interface is returned.
471 @retval EFI_SUCCESS The interface information for the specified protocol was returned.
472 @retval EFI_UNSUPPORTED The device does not support the specified protocol.
473 @retval EFI_INVALID_PARAMETER Handle is not a valid EFI_HANDLE..
474 @retval EFI_INVALID_PARAMETER Protocol is NULL.
475 @retval EFI_INVALID_PARAMETER Interface is NULL.
481 IN EFI_HANDLE UserHandle
,
482 IN EFI_GUID
*Protocol
,
487 PROTOCOL_INTERFACE
*Prot
;
490 // Check for invalid Protocol
492 if (Protocol
== NULL
) {
493 return EFI_INVALID_PARAMETER
;
497 // Check for invalid Interface
499 if (Interface
== NULL
) {
500 return EFI_INVALID_PARAMETER
;
506 // Check for invalid UserHandle
508 Status
= MmValidateHandle (UserHandle
);
509 if (EFI_ERROR (Status
)) {
514 // Look at each protocol interface for a match
516 Prot
= MmGetProtocolInterface (UserHandle
, Protocol
);
518 return EFI_UNSUPPORTED
;
522 // This is the protocol interface entry for this protocol
524 *Interface
= Prot
->Interface
;