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
;
39 if (Handle
->Signature
!= EFI_HANDLE_SIGNATURE
) {
40 return EFI_INVALID_PARAMETER
;
47 Finds the protocol entry for the requested protocol.
49 @param Protocol The ID of the protocol
50 @param Create Create a new entry if not found
52 @return Protocol entry
56 SmmFindProtocolEntry (
57 IN EFI_GUID
*Protocol
,
63 PROTOCOL_ENTRY
*ProtEntry
;
66 // Search the database for the matching GUID
70 for (Link
= mProtocolDatabase
.ForwardLink
;
71 Link
!= &mProtocolDatabase
;
72 Link
= Link
->ForwardLink
)
74 Item
= CR (Link
, PROTOCOL_ENTRY
, AllEntries
, PROTOCOL_ENTRY_SIGNATURE
);
75 if (CompareGuid (&Item
->ProtocolID
, Protocol
)) {
77 // This is the protocol entry
85 // If the protocol entry was not found and Create is TRUE, then
86 // allocate a new entry
88 if ((ProtEntry
== NULL
) && Create
) {
89 ProtEntry
= AllocatePool (sizeof (PROTOCOL_ENTRY
));
90 if (ProtEntry
!= NULL
) {
92 // Initialize new protocol entry structure
94 ProtEntry
->Signature
= PROTOCOL_ENTRY_SIGNATURE
;
95 CopyGuid ((VOID
*)&ProtEntry
->ProtocolID
, Protocol
);
96 InitializeListHead (&ProtEntry
->Protocols
);
97 InitializeListHead (&ProtEntry
->Notify
);
100 // Add it to protocol database
102 InsertTailList (&mProtocolDatabase
, &ProtEntry
->AllEntries
);
110 Finds the protocol instance for the requested handle and protocol.
111 Note: This function doesn't do parameters checking, it's caller's responsibility
112 to pass in valid parameters.
114 @param Handle The handle to search the protocol on
115 @param Protocol GUID of the protocol
116 @param Interface The interface for the protocol being searched
118 @return Protocol instance (NULL: Not found)
122 SmmFindProtocolInterface (
124 IN EFI_GUID
*Protocol
,
128 PROTOCOL_INTERFACE
*Prot
;
129 PROTOCOL_ENTRY
*ProtEntry
;
135 // Lookup the protocol entry for this protocol ID
137 ProtEntry
= SmmFindProtocolEntry (Protocol
, FALSE
);
138 if (ProtEntry
!= NULL
) {
140 // Look at each protocol interface for any matches
142 for (Link
= Handle
->Protocols
.ForwardLink
; Link
!= &Handle
->Protocols
; Link
= Link
->ForwardLink
) {
144 // If this protocol interface matches, remove it
146 Prot
= CR (Link
, PROTOCOL_INTERFACE
, Link
, PROTOCOL_INTERFACE_SIGNATURE
);
147 if ((Prot
->Interface
== Interface
) && (Prot
->Protocol
== ProtEntry
)) {
159 Wrapper function to SmmInstallProtocolInterfaceNotify. This is the public API which
160 Calls the private one which contains a BOOLEAN parameter for notifications
162 @param UserHandle The handle to install the protocol handler on,
163 or NULL if a new handle is to be allocated
164 @param Protocol The protocol to add to the handle
165 @param InterfaceType Indicates whether Interface is supplied in
167 @param Interface The interface for the protocol being added
174 SmmInstallProtocolInterface (
175 IN OUT EFI_HANDLE
*UserHandle
,
176 IN EFI_GUID
*Protocol
,
177 IN EFI_INTERFACE_TYPE InterfaceType
,
181 return SmmInstallProtocolInterfaceNotify (
191 Installs a protocol interface into the boot services environment.
193 @param UserHandle The handle to install the protocol handler on,
194 or NULL if a new handle is to be allocated
195 @param Protocol The protocol to add to the handle
196 @param InterfaceType Indicates whether Interface is supplied in
198 @param Interface The interface for the protocol being added
199 @param Notify indicates whether notify the notification list
202 @retval EFI_INVALID_PARAMETER Invalid parameter
203 @retval EFI_OUT_OF_RESOURCES No enough buffer to allocate
204 @retval EFI_SUCCESS Protocol interface successfully installed
208 SmmInstallProtocolInterfaceNotify (
209 IN OUT EFI_HANDLE
*UserHandle
,
210 IN EFI_GUID
*Protocol
,
211 IN EFI_INTERFACE_TYPE InterfaceType
,
216 PROTOCOL_INTERFACE
*Prot
;
217 PROTOCOL_ENTRY
*ProtEntry
;
220 VOID
*ExistingInterface
;
223 // returns EFI_INVALID_PARAMETER if InterfaceType is invalid.
224 // Also added check for invalid UserHandle and Protocol pointers.
226 if ((UserHandle
== NULL
) || (Protocol
== NULL
)) {
227 return EFI_INVALID_PARAMETER
;
230 if (InterfaceType
!= EFI_NATIVE_INTERFACE
) {
231 return EFI_INVALID_PARAMETER
;
235 // Print debug message
237 DEBUG ((DEBUG_LOAD
| DEBUG_INFO
, "SmmInstallProtocolInterface: %g %p\n", Protocol
, Interface
));
239 Status
= EFI_OUT_OF_RESOURCES
;
243 if (*UserHandle
!= NULL
) {
244 Status
= SmmHandleProtocol (*UserHandle
, Protocol
, (VOID
**)&ExistingInterface
);
245 if (!EFI_ERROR (Status
)) {
246 return EFI_INVALID_PARAMETER
;
251 // Lookup the Protocol Entry for the requested protocol
253 ProtEntry
= SmmFindProtocolEntry (Protocol
, TRUE
);
254 if (ProtEntry
== NULL
) {
259 // Allocate a new protocol interface structure
261 Prot
= AllocateZeroPool (sizeof (PROTOCOL_INTERFACE
));
263 Status
= EFI_OUT_OF_RESOURCES
;
268 // If caller didn't supply a handle, allocate a new one
270 Handle
= (IHANDLE
*)*UserHandle
;
271 if (Handle
== NULL
) {
272 Handle
= AllocateZeroPool (sizeof (IHANDLE
));
273 if (Handle
== NULL
) {
274 Status
= EFI_OUT_OF_RESOURCES
;
279 // Initialize new handler structure
281 Handle
->Signature
= EFI_HANDLE_SIGNATURE
;
282 InitializeListHead (&Handle
->Protocols
);
285 // Add this handle to the list global list of all handles
288 InsertTailList (&gHandleList
, &Handle
->AllHandles
);
290 Status
= SmmValidateHandle (Handle
);
291 if (EFI_ERROR (Status
)) {
292 DEBUG ((DEBUG_ERROR
, "SmmInstallProtocolInterface: input handle at 0x%x is invalid\n", Handle
));
298 // Each interface that is added must be unique
300 ASSERT (SmmFindProtocolInterface (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 SmmNotifyProtocol (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
345 DEBUG ((DEBUG_ERROR
, "SmmInstallProtocolInterface: %g %p failed with %r\n", Protocol
, Interface
, Status
));
352 Uninstalls all instances of a protocol:interfacer from a handle.
353 If the last protocol interface is remove from the handle, the
356 @param UserHandle The handle to remove the protocol handler from
357 @param Protocol The protocol, of protocol:interface, to remove
358 @param Interface The interface, of protocol:interface, to remove
360 @retval EFI_INVALID_PARAMETER Protocol is NULL.
361 @retval EFI_SUCCESS Protocol interface successfully uninstalled.
366 SmmUninstallProtocolInterface (
367 IN EFI_HANDLE UserHandle
,
368 IN EFI_GUID
*Protocol
,
374 PROTOCOL_INTERFACE
*Prot
;
377 // Check that Protocol is valid
379 if (Protocol
== NULL
) {
380 return EFI_INVALID_PARAMETER
;
384 // Check that UserHandle is a valid handle
386 Status
= SmmValidateHandle (UserHandle
);
387 if (EFI_ERROR (Status
)) {
392 // Check that Protocol exists on UserHandle, and Interface matches the interface in the database
394 Prot
= SmmFindProtocolInterface (UserHandle
, Protocol
, Interface
);
396 return EFI_NOT_FOUND
;
400 // Remove the protocol interface from the protocol
402 Status
= EFI_NOT_FOUND
;
403 Handle
= (IHANDLE
*)UserHandle
;
404 Prot
= SmmRemoveInterfaceFromProtocol (Handle
, Protocol
, Interface
);
408 // Remove the protocol interface from the handle
410 RemoveEntryList (&Prot
->Link
);
417 Status
= EFI_SUCCESS
;
421 // If there are no more handlers for the handle, free the handle
423 if (IsListEmpty (&Handle
->Protocols
)) {
424 Handle
->Signature
= 0;
425 RemoveEntryList (&Handle
->AllHandles
);
433 Locate a certain GUID protocol interface in a Handle's protocols.
435 @param UserHandle The handle to obtain the protocol interface on
436 @param Protocol The GUID of the protocol
438 @return The requested protocol interface for the handle
442 SmmGetProtocolInterface (
443 IN EFI_HANDLE UserHandle
,
444 IN EFI_GUID
*Protocol
448 PROTOCOL_ENTRY
*ProtEntry
;
449 PROTOCOL_INTERFACE
*Prot
;
453 Status
= SmmValidateHandle (UserHandle
);
454 if (EFI_ERROR (Status
)) {
458 Handle
= (IHANDLE
*)UserHandle
;
461 // Look at each protocol interface for a match
463 for (Link
= Handle
->Protocols
.ForwardLink
; Link
!= &Handle
->Protocols
; Link
= Link
->ForwardLink
) {
464 Prot
= CR (Link
, PROTOCOL_INTERFACE
, Link
, PROTOCOL_INTERFACE_SIGNATURE
);
465 ProtEntry
= Prot
->Protocol
;
466 if (CompareGuid (&ProtEntry
->ProtocolID
, Protocol
)) {
475 Queries a handle to determine if it supports a specified protocol.
477 @param UserHandle The handle being queried.
478 @param Protocol The published unique identifier of the protocol.
479 @param Interface Supplies the address where a pointer to the
480 corresponding Protocol Interface is returned.
482 @retval EFI_SUCCESS The interface information for the specified protocol was returned.
483 @retval EFI_UNSUPPORTED The device does not support the specified protocol.
484 @retval EFI_INVALID_PARAMETER Handle is not a valid EFI_HANDLE..
485 @retval EFI_INVALID_PARAMETER Protocol is NULL.
486 @retval EFI_INVALID_PARAMETER Interface is NULL.
492 IN EFI_HANDLE UserHandle
,
493 IN EFI_GUID
*Protocol
,
498 PROTOCOL_INTERFACE
*Prot
;
501 // Check for invalid Protocol
503 if (Protocol
== NULL
) {
504 return EFI_INVALID_PARAMETER
;
508 // Check for invalid Interface
510 if (Interface
== NULL
) {
511 return EFI_INVALID_PARAMETER
;
517 // Check for invalid UserHandle
519 Status
= SmmValidateHandle (UserHandle
);
520 if (EFI_ERROR (Status
)) {
525 // Look at each protocol interface for a match
527 Prot
= SmmGetProtocolInterface (UserHandle
, Protocol
);
529 return EFI_UNSUPPORTED
;
533 // This is the protocol interface entry for this protocol
535 *Interface
= Prot
->Interface
;