2 SMM handle & protocol handling.
4 Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
12 // mProtocolDatabase - A list of all protocols in the system. (simple list for now)
13 // gHandleList - A list of all the handles in the system
15 LIST_ENTRY mProtocolDatabase
= INITIALIZE_LIST_HEAD_VARIABLE (mProtocolDatabase
);
16 LIST_ENTRY gHandleList
= INITIALIZE_LIST_HEAD_VARIABLE (gHandleList
);
19 Check whether a handle is a valid EFI_HANDLE
21 @param UserHandle The handle to check
23 @retval EFI_INVALID_PARAMETER The handle is NULL or not a valid EFI_HANDLE.
24 @retval EFI_SUCCESS The handle is valid EFI_HANDLE.
29 IN EFI_HANDLE UserHandle
34 Handle
= (IHANDLE
*)UserHandle
;
36 return EFI_INVALID_PARAMETER
;
38 if (Handle
->Signature
!= EFI_HANDLE_SIGNATURE
) {
39 return EFI_INVALID_PARAMETER
;
45 Finds the protocol entry for the requested protocol.
47 @param Protocol The ID of the protocol
48 @param Create Create a new entry if not found
50 @return Protocol entry
54 SmmFindProtocolEntry (
55 IN EFI_GUID
*Protocol
,
61 PROTOCOL_ENTRY
*ProtEntry
;
64 // Search the database for the matching GUID
68 for (Link
= mProtocolDatabase
.ForwardLink
;
69 Link
!= &mProtocolDatabase
;
70 Link
= Link
->ForwardLink
) {
72 Item
= CR(Link
, PROTOCOL_ENTRY
, AllEntries
, PROTOCOL_ENTRY_SIGNATURE
);
73 if (CompareGuid (&Item
->ProtocolID
, Protocol
)) {
75 // This is the protocol entry
83 // If the protocol entry was not found and Create is TRUE, then
84 // allocate a new entry
86 if ((ProtEntry
== NULL
) && Create
) {
87 ProtEntry
= AllocatePool (sizeof(PROTOCOL_ENTRY
));
88 if (ProtEntry
!= NULL
) {
90 // Initialize new protocol entry structure
92 ProtEntry
->Signature
= PROTOCOL_ENTRY_SIGNATURE
;
93 CopyGuid ((VOID
*)&ProtEntry
->ProtocolID
, Protocol
);
94 InitializeListHead (&ProtEntry
->Protocols
);
95 InitializeListHead (&ProtEntry
->Notify
);
98 // Add it to protocol database
100 InsertTailList (&mProtocolDatabase
, &ProtEntry
->AllEntries
);
107 Finds the protocol instance for the requested handle and protocol.
108 Note: This function doesn't do parameters checking, it's caller's responsibility
109 to pass in valid parameters.
111 @param Handle The handle to search the protocol on
112 @param Protocol GUID of the protocol
113 @param Interface The interface for the protocol being searched
115 @return Protocol instance (NULL: Not found)
119 SmmFindProtocolInterface (
121 IN EFI_GUID
*Protocol
,
125 PROTOCOL_INTERFACE
*Prot
;
126 PROTOCOL_ENTRY
*ProtEntry
;
132 // Lookup the protocol entry for this protocol ID
134 ProtEntry
= SmmFindProtocolEntry (Protocol
, FALSE
);
135 if (ProtEntry
!= NULL
) {
137 // Look at each protocol interface for any matches
139 for (Link
= Handle
->Protocols
.ForwardLink
; Link
!= &Handle
->Protocols
; Link
=Link
->ForwardLink
) {
141 // If this protocol interface matches, remove it
143 Prot
= CR(Link
, PROTOCOL_INTERFACE
, Link
, PROTOCOL_INTERFACE_SIGNATURE
);
144 if (Prot
->Interface
== Interface
&& Prot
->Protocol
== ProtEntry
) {
154 Wrapper function to SmmInstallProtocolInterfaceNotify. This is the public API which
155 Calls the private one which contains a BOOLEAN parameter for notifications
157 @param UserHandle The handle to install the protocol handler on,
158 or NULL if a new handle is to be allocated
159 @param Protocol The protocol to add to the handle
160 @param InterfaceType Indicates whether Interface is supplied in
162 @param Interface The interface for the protocol being added
169 SmmInstallProtocolInterface (
170 IN OUT EFI_HANDLE
*UserHandle
,
171 IN EFI_GUID
*Protocol
,
172 IN EFI_INTERFACE_TYPE InterfaceType
,
176 return SmmInstallProtocolInterfaceNotify (
186 Installs a protocol interface into the boot services environment.
188 @param UserHandle The handle to install the protocol handler on,
189 or NULL if a new handle is to be allocated
190 @param Protocol The protocol to add to the handle
191 @param InterfaceType Indicates whether Interface is supplied in
193 @param Interface The interface for the protocol being added
194 @param Notify indicates whether notify the notification list
197 @retval EFI_INVALID_PARAMETER Invalid parameter
198 @retval EFI_OUT_OF_RESOURCES No enough buffer to allocate
199 @retval EFI_SUCCESS Protocol interface successfully installed
203 SmmInstallProtocolInterfaceNotify (
204 IN OUT EFI_HANDLE
*UserHandle
,
205 IN EFI_GUID
*Protocol
,
206 IN EFI_INTERFACE_TYPE InterfaceType
,
211 PROTOCOL_INTERFACE
*Prot
;
212 PROTOCOL_ENTRY
*ProtEntry
;
215 VOID
*ExistingInterface
;
218 // returns EFI_INVALID_PARAMETER if InterfaceType is invalid.
219 // Also added check for invalid UserHandle and Protocol pointers.
221 if (UserHandle
== NULL
|| Protocol
== NULL
) {
222 return EFI_INVALID_PARAMETER
;
225 if (InterfaceType
!= EFI_NATIVE_INTERFACE
) {
226 return EFI_INVALID_PARAMETER
;
230 // Print debug message
232 DEBUG((DEBUG_LOAD
| DEBUG_INFO
, "SmmInstallProtocolInterface: %g %p\n", Protocol
, Interface
));
234 Status
= EFI_OUT_OF_RESOURCES
;
238 if (*UserHandle
!= NULL
) {
239 Status
= SmmHandleProtocol (*UserHandle
, Protocol
, (VOID
**)&ExistingInterface
);
240 if (!EFI_ERROR (Status
)) {
241 return EFI_INVALID_PARAMETER
;
246 // Lookup the Protocol Entry for the requested protocol
248 ProtEntry
= SmmFindProtocolEntry (Protocol
, TRUE
);
249 if (ProtEntry
== NULL
) {
254 // Allocate a new protocol interface structure
256 Prot
= AllocateZeroPool (sizeof(PROTOCOL_INTERFACE
));
258 Status
= EFI_OUT_OF_RESOURCES
;
263 // If caller didn't supply a handle, allocate a new one
265 Handle
= (IHANDLE
*)*UserHandle
;
266 if (Handle
== NULL
) {
267 Handle
= AllocateZeroPool (sizeof(IHANDLE
));
268 if (Handle
== NULL
) {
269 Status
= EFI_OUT_OF_RESOURCES
;
274 // Initialize new handler structure
276 Handle
->Signature
= EFI_HANDLE_SIGNATURE
;
277 InitializeListHead (&Handle
->Protocols
);
280 // Add this handle to the list global list of all handles
283 InsertTailList (&gHandleList
, &Handle
->AllHandles
);
285 Status
= SmmValidateHandle (Handle
);
286 if (EFI_ERROR (Status
)) {
287 DEBUG((DEBUG_ERROR
, "SmmInstallProtocolInterface: input handle at 0x%x is invalid\n", Handle
));
293 // Each interface that is added must be unique
295 ASSERT (SmmFindProtocolInterface (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 SmmNotifyProtocol (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
338 DEBUG((DEBUG_ERROR
, "SmmInstallProtocolInterface: %g %p failed with %r\n", Protocol
, Interface
, Status
));
344 Uninstalls all instances of a protocol:interfacer from a handle.
345 If the last protocol interface is remove from the handle, the
348 @param UserHandle The handle to remove the protocol handler from
349 @param Protocol The protocol, of protocol:interface, to remove
350 @param Interface The interface, of protocol:interface, to remove
352 @retval EFI_INVALID_PARAMETER Protocol is NULL.
353 @retval EFI_SUCCESS Protocol interface successfully uninstalled.
358 SmmUninstallProtocolInterface (
359 IN EFI_HANDLE UserHandle
,
360 IN EFI_GUID
*Protocol
,
366 PROTOCOL_INTERFACE
*Prot
;
369 // Check that Protocol is valid
371 if (Protocol
== NULL
) {
372 return EFI_INVALID_PARAMETER
;
376 // Check that UserHandle is a valid handle
378 Status
= SmmValidateHandle (UserHandle
);
379 if (EFI_ERROR (Status
)) {
384 // Check that Protocol exists on UserHandle, and Interface matches the interface in the database
386 Prot
= SmmFindProtocolInterface (UserHandle
, Protocol
, Interface
);
388 return EFI_NOT_FOUND
;
392 // Remove the protocol interface from the protocol
394 Status
= EFI_NOT_FOUND
;
395 Handle
= (IHANDLE
*)UserHandle
;
396 Prot
= SmmRemoveInterfaceFromProtocol (Handle
, Protocol
, Interface
);
400 // Remove the protocol interface from the handle
402 RemoveEntryList (&Prot
->Link
);
409 Status
= EFI_SUCCESS
;
413 // If there are no more handlers for the handle, free the handle
415 if (IsListEmpty (&Handle
->Protocols
)) {
416 Handle
->Signature
= 0;
417 RemoveEntryList (&Handle
->AllHandles
);
424 Locate a certain GUID protocol interface in a Handle's protocols.
426 @param UserHandle The handle to obtain the protocol interface on
427 @param Protocol The GUID of the protocol
429 @return The requested protocol interface for the handle
433 SmmGetProtocolInterface (
434 IN EFI_HANDLE UserHandle
,
435 IN EFI_GUID
*Protocol
439 PROTOCOL_ENTRY
*ProtEntry
;
440 PROTOCOL_INTERFACE
*Prot
;
444 Status
= SmmValidateHandle (UserHandle
);
445 if (EFI_ERROR (Status
)) {
449 Handle
= (IHANDLE
*)UserHandle
;
452 // Look at each protocol interface for a match
454 for (Link
= Handle
->Protocols
.ForwardLink
; Link
!= &Handle
->Protocols
; Link
= Link
->ForwardLink
) {
455 Prot
= CR(Link
, PROTOCOL_INTERFACE
, Link
, PROTOCOL_INTERFACE_SIGNATURE
);
456 ProtEntry
= Prot
->Protocol
;
457 if (CompareGuid (&ProtEntry
->ProtocolID
, Protocol
)) {
465 Queries a handle to determine if it supports a specified protocol.
467 @param UserHandle The handle being queried.
468 @param Protocol The published unique identifier of the protocol.
469 @param Interface Supplies the address where a pointer to the
470 corresponding Protocol Interface is returned.
472 @retval EFI_SUCCESS The interface information for the specified protocol was returned.
473 @retval EFI_UNSUPPORTED The device does not support the specified protocol.
474 @retval EFI_INVALID_PARAMETER Handle is not a valid EFI_HANDLE..
475 @retval EFI_INVALID_PARAMETER Protocol is NULL.
476 @retval EFI_INVALID_PARAMETER Interface is NULL.
482 IN EFI_HANDLE UserHandle
,
483 IN EFI_GUID
*Protocol
,
488 PROTOCOL_INTERFACE
*Prot
;
491 // Check for invalid Protocol
493 if (Protocol
== NULL
) {
494 return EFI_INVALID_PARAMETER
;
498 // Check for invalid Interface
500 if (Interface
== NULL
) {
501 return EFI_INVALID_PARAMETER
;
507 // Check for invalid UserHandle
509 Status
= SmmValidateHandle (UserHandle
);
510 if (EFI_ERROR (Status
)) {
515 // Look at each protocol interface for a match
517 Prot
= SmmGetProtocolInterface (UserHandle
, Protocol
);
519 return EFI_UNSUPPORTED
;
523 // This is the protocol interface entry for this protocol
525 *Interface
= Prot
->Interface
;