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
;
40 if (Handle
->Signature
!= EFI_HANDLE_SIGNATURE
) {
41 return EFI_INVALID_PARAMETER
;
48 Finds the protocol entry for the requested protocol.
50 @param Protocol The ID of the protocol
51 @param Create Create a new entry if not found
53 @return Protocol entry
58 IN EFI_GUID
*Protocol
,
64 PROTOCOL_ENTRY
*ProtEntry
;
67 // Search the database for the matching GUID
71 for (Link
= mProtocolDatabase
.ForwardLink
;
72 Link
!= &mProtocolDatabase
;
73 Link
= Link
->ForwardLink
)
75 Item
= CR (Link
, PROTOCOL_ENTRY
, AllEntries
, PROTOCOL_ENTRY_SIGNATURE
);
76 if (CompareGuid (&Item
->ProtocolID
, Protocol
)) {
78 // This is the protocol entry
86 // If the protocol entry was not found and Create is TRUE, then
87 // allocate a new entry
89 if ((ProtEntry
== NULL
) && Create
) {
90 ProtEntry
= AllocatePool (sizeof (PROTOCOL_ENTRY
));
91 if (ProtEntry
!= NULL
) {
93 // Initialize new protocol entry structure
95 ProtEntry
->Signature
= PROTOCOL_ENTRY_SIGNATURE
;
96 CopyGuid ((VOID
*)&ProtEntry
->ProtocolID
, Protocol
);
97 InitializeListHead (&ProtEntry
->Protocols
);
98 InitializeListHead (&ProtEntry
->Notify
);
101 // Add it to protocol database
103 InsertTailList (&mProtocolDatabase
, &ProtEntry
->AllEntries
);
111 Finds the protocol instance for the requested handle and protocol.
112 Note: This function doesn't do parameters checking, it's caller's responsibility
113 to pass in valid parameters.
115 @param Handle The handle to search the protocol on
116 @param Protocol GUID of the protocol
117 @param Interface The interface for the protocol being searched
119 @return Protocol instance (NULL: Not found)
123 MmFindProtocolInterface (
125 IN EFI_GUID
*Protocol
,
129 PROTOCOL_INTERFACE
*Prot
;
130 PROTOCOL_ENTRY
*ProtEntry
;
136 // Lookup the protocol entry for this protocol ID
138 ProtEntry
= MmFindProtocolEntry (Protocol
, FALSE
);
139 if (ProtEntry
!= NULL
) {
141 // Look at each protocol interface for any matches
143 for (Link
= Handle
->Protocols
.ForwardLink
; Link
!= &Handle
->Protocols
; Link
= Link
->ForwardLink
) {
145 // If this protocol interface matches, remove it
147 Prot
= CR (Link
, PROTOCOL_INTERFACE
, Link
, PROTOCOL_INTERFACE_SIGNATURE
);
148 if ((Prot
->Interface
== Interface
) && (Prot
->Protocol
== ProtEntry
)) {
160 Wrapper function to MmInstallProtocolInterfaceNotify. This is the public API which
161 Calls the private one which contains a BOOLEAN parameter for notifications
163 @param UserHandle The handle to install the protocol handler on,
164 or NULL if a new handle is to be allocated
165 @param Protocol The protocol to add to the handle
166 @param InterfaceType Indicates whether Interface is supplied in
168 @param Interface The interface for the protocol being added
175 MmInstallProtocolInterface (
176 IN OUT EFI_HANDLE
*UserHandle
,
177 IN EFI_GUID
*Protocol
,
178 IN EFI_INTERFACE_TYPE InterfaceType
,
182 return MmInstallProtocolInterfaceNotify (
192 Installs a protocol interface into the boot services environment.
194 @param UserHandle The handle to install the protocol handler on,
195 or NULL if a new handle is to be allocated
196 @param Protocol The protocol to add to the handle
197 @param InterfaceType Indicates whether Interface is supplied in
199 @param Interface The interface for the protocol being added
200 @param Notify indicates whether notify the notification list
203 @retval EFI_INVALID_PARAMETER Invalid parameter
204 @retval EFI_OUT_OF_RESOURCES No enough buffer to allocate
205 @retval EFI_SUCCESS Protocol interface successfully installed
209 MmInstallProtocolInterfaceNotify (
210 IN OUT EFI_HANDLE
*UserHandle
,
211 IN EFI_GUID
*Protocol
,
212 IN EFI_INTERFACE_TYPE InterfaceType
,
217 PROTOCOL_INTERFACE
*Prot
;
218 PROTOCOL_ENTRY
*ProtEntry
;
221 VOID
*ExistingInterface
;
224 // returns EFI_INVALID_PARAMETER if InterfaceType is invalid.
225 // Also added check for invalid UserHandle and Protocol pointers.
227 if ((UserHandle
== NULL
) || (Protocol
== NULL
)) {
228 return EFI_INVALID_PARAMETER
;
231 if (InterfaceType
!= EFI_NATIVE_INTERFACE
) {
232 return EFI_INVALID_PARAMETER
;
236 // Print debug message
238 DEBUG ((DEBUG_LOAD
| DEBUG_INFO
, "MmInstallProtocolInterface: %g %p\n", Protocol
, Interface
));
240 Status
= EFI_OUT_OF_RESOURCES
;
244 if (*UserHandle
!= NULL
) {
245 Status
= MmHandleProtocol (*UserHandle
, Protocol
, (VOID
**)&ExistingInterface
);
246 if (!EFI_ERROR (Status
)) {
247 return EFI_INVALID_PARAMETER
;
252 // Lookup the Protocol Entry for the requested protocol
254 ProtEntry
= MmFindProtocolEntry (Protocol
, TRUE
);
255 if (ProtEntry
== NULL
) {
260 // Allocate a new protocol interface structure
262 Prot
= AllocateZeroPool (sizeof (PROTOCOL_INTERFACE
));
264 Status
= EFI_OUT_OF_RESOURCES
;
269 // If caller didn't supply a handle, allocate a new one
271 Handle
= (IHANDLE
*)*UserHandle
;
272 if (Handle
== NULL
) {
273 Handle
= AllocateZeroPool (sizeof (IHANDLE
));
274 if (Handle
== NULL
) {
275 Status
= EFI_OUT_OF_RESOURCES
;
280 // Initialize new handler structure
282 Handle
->Signature
= EFI_HANDLE_SIGNATURE
;
283 InitializeListHead (&Handle
->Protocols
);
286 // Add this handle to the list global list of all handles
289 InsertTailList (&gHandleList
, &Handle
->AllHandles
);
292 Status
= MmValidateHandle (Handle
);
293 if (EFI_ERROR (Status
)) {
298 // Each interface that is added must be unique
300 ASSERT (MmFindProtocolInterface (Handle
, Protocol
, Interface
) == NULL
);
303 // Initialize the protocol interface structure
305 Prot
->Signature
= PROTOCOL_INTERFACE_SIGNATURE
;
306 Prot
->Handle
= Handle
;
307 Prot
->Protocol
= ProtEntry
;
308 Prot
->Interface
= Interface
;
311 // Add this protocol interface to the head of the supported
312 // protocol list for this handle
314 InsertHeadList (&Handle
->Protocols
, &Prot
->Link
);
317 // Add this protocol interface to the tail of the
320 InsertTailList (&ProtEntry
->Protocols
, &Prot
->ByProtocol
);
323 // Notify the notification list for this protocol
326 MmNotifyProtocol (Prot
);
329 Status
= EFI_SUCCESS
;
332 if (!EFI_ERROR (Status
)) {
334 // Return the new handle back to the caller
336 *UserHandle
= Handle
;
339 // There was an error, clean up
350 Uninstalls all instances of a protocol:interfacer from a handle.
351 If the last protocol interface is remove from the handle, the
354 @param UserHandle The handle to remove the protocol handler from
355 @param Protocol The protocol, of protocol:interface, to remove
356 @param Interface The interface, of protocol:interface, to remove
358 @retval EFI_INVALID_PARAMETER Protocol is NULL.
359 @retval EFI_SUCCESS Protocol interface successfully uninstalled.
364 MmUninstallProtocolInterface (
365 IN EFI_HANDLE UserHandle
,
366 IN EFI_GUID
*Protocol
,
372 PROTOCOL_INTERFACE
*Prot
;
375 // Check that Protocol is valid
377 if (Protocol
== NULL
) {
378 return EFI_INVALID_PARAMETER
;
382 // Check that UserHandle is a valid handle
384 Status
= MmValidateHandle (UserHandle
);
385 if (EFI_ERROR (Status
)) {
390 // Check that Protocol exists on UserHandle, and Interface matches the interface in the database
392 Prot
= MmFindProtocolInterface (UserHandle
, Protocol
, Interface
);
394 return EFI_NOT_FOUND
;
398 // Remove the protocol interface from the protocol
400 Status
= EFI_NOT_FOUND
;
401 Handle
= (IHANDLE
*)UserHandle
;
402 Prot
= MmRemoveInterfaceFromProtocol (Handle
, Protocol
, Interface
);
406 // Remove the protocol interface from the handle
408 RemoveEntryList (&Prot
->Link
);
415 Status
= EFI_SUCCESS
;
419 // If there are no more handlers for the handle, free the handle
421 if (IsListEmpty (&Handle
->Protocols
)) {
422 Handle
->Signature
= 0;
423 RemoveEntryList (&Handle
->AllHandles
);
431 Locate a certain GUID protocol interface in a Handle's protocols.
433 @param UserHandle The handle to obtain the protocol interface on
434 @param Protocol The GUID of the protocol
436 @return The requested protocol interface for the handle
440 MmGetProtocolInterface (
441 IN EFI_HANDLE UserHandle
,
442 IN EFI_GUID
*Protocol
446 PROTOCOL_ENTRY
*ProtEntry
;
447 PROTOCOL_INTERFACE
*Prot
;
451 Status
= MmValidateHandle (UserHandle
);
452 if (EFI_ERROR (Status
)) {
456 Handle
= (IHANDLE
*)UserHandle
;
459 // Look at each protocol interface for a match
461 for (Link
= Handle
->Protocols
.ForwardLink
; Link
!= &Handle
->Protocols
; Link
= Link
->ForwardLink
) {
462 Prot
= CR (Link
, PROTOCOL_INTERFACE
, Link
, PROTOCOL_INTERFACE_SIGNATURE
);
463 ProtEntry
= Prot
->Protocol
;
464 if (CompareGuid (&ProtEntry
->ProtocolID
, Protocol
)) {
473 Queries a handle to determine if it supports a specified protocol.
475 @param UserHandle The handle being queried.
476 @param Protocol The published unique identifier of the protocol.
477 @param Interface Supplies the address where a pointer to the
478 corresponding Protocol Interface is returned.
480 @retval EFI_SUCCESS The interface information for the specified protocol was returned.
481 @retval EFI_UNSUPPORTED The device does not support the specified protocol.
482 @retval EFI_INVALID_PARAMETER Handle is not a valid EFI_HANDLE..
483 @retval EFI_INVALID_PARAMETER Protocol is NULL.
484 @retval EFI_INVALID_PARAMETER Interface is NULL.
490 IN EFI_HANDLE UserHandle
,
491 IN EFI_GUID
*Protocol
,
496 PROTOCOL_INTERFACE
*Prot
;
499 // Check for invalid Protocol
501 if (Protocol
== NULL
) {
502 return EFI_INVALID_PARAMETER
;
506 // Check for invalid Interface
508 if (Interface
== NULL
) {
509 return EFI_INVALID_PARAMETER
;
515 // Check for invalid UserHandle
517 Status
= MmValidateHandle (UserHandle
);
518 if (EFI_ERROR (Status
)) {
523 // Look at each protocol interface for a match
525 Prot
= MmGetProtocolInterface (UserHandle
, Protocol
);
527 return EFI_UNSUPPORTED
;
531 // This is the protocol interface entry for this protocol
533 *Interface
= Prot
->Interface
;