2 SMM handle & protocol handling.
4 Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials are licensed and made available
6 under the terms and conditions of the BSD License which accompanies this
7 distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
15 #include "PiSmmCore.h"
18 // mProtocolDatabase - A list of all protocols in the system. (simple list for now)
19 // gHandleList - A list of all the handles in the system
21 LIST_ENTRY mProtocolDatabase
= INITIALIZE_LIST_HEAD_VARIABLE (mProtocolDatabase
);
22 LIST_ENTRY gHandleList
= INITIALIZE_LIST_HEAD_VARIABLE (gHandleList
);
25 Check whether a handle is a valid EFI_HANDLE
27 @param UserHandle The handle to check
29 @retval EFI_INVALID_PARAMETER The handle is NULL or not a valid EFI_HANDLE.
30 @retval EFI_SUCCESS The handle is valid EFI_HANDLE.
35 IN EFI_HANDLE UserHandle
40 Handle
= (IHANDLE
*)UserHandle
;
42 return EFI_INVALID_PARAMETER
;
44 if (Handle
->Signature
!= EFI_HANDLE_SIGNATURE
) {
45 return EFI_INVALID_PARAMETER
;
51 Finds the protocol entry for the requested protocol.
53 @param Protocol The ID of the protocol
54 @param Create Create a new entry if not found
56 @return Protocol entry
60 SmmFindProtocolEntry (
61 IN EFI_GUID
*Protocol
,
67 PROTOCOL_ENTRY
*ProtEntry
;
70 // Search the database for the matching GUID
74 for (Link
= mProtocolDatabase
.ForwardLink
;
75 Link
!= &mProtocolDatabase
;
76 Link
= Link
->ForwardLink
) {
78 Item
= CR(Link
, PROTOCOL_ENTRY
, AllEntries
, PROTOCOL_ENTRY_SIGNATURE
);
79 if (CompareGuid (&Item
->ProtocolID
, Protocol
)) {
81 // This is the protocol entry
89 // If the protocol entry was not found and Create is TRUE, then
90 // allocate a new entry
92 if ((ProtEntry
== NULL
) && Create
) {
93 ProtEntry
= AllocatePool (sizeof(PROTOCOL_ENTRY
));
94 if (ProtEntry
!= NULL
) {
96 // Initialize new protocol entry structure
98 ProtEntry
->Signature
= PROTOCOL_ENTRY_SIGNATURE
;
99 CopyGuid ((VOID
*)&ProtEntry
->ProtocolID
, Protocol
);
100 InitializeListHead (&ProtEntry
->Protocols
);
101 InitializeListHead (&ProtEntry
->Notify
);
104 // Add it to protocol database
106 InsertTailList (&mProtocolDatabase
, &ProtEntry
->AllEntries
);
113 Finds the protocol instance for the requested handle and protocol.
114 Note: This function doesn't do parameters checking, it's caller's responsibility
115 to pass in valid parameters.
117 @param Handle The handle to search the protocol on
118 @param Protocol GUID of the protocol
119 @param Interface The interface for the protocol being searched
121 @return Protocol instance (NULL: Not found)
125 SmmFindProtocolInterface (
127 IN EFI_GUID
*Protocol
,
131 PROTOCOL_INTERFACE
*Prot
;
132 PROTOCOL_ENTRY
*ProtEntry
;
138 // Lookup the protocol entry for this protocol ID
140 ProtEntry
= SmmFindProtocolEntry (Protocol
, FALSE
);
141 if (ProtEntry
!= NULL
) {
143 // Look at each protocol interface for any matches
145 for (Link
= Handle
->Protocols
.ForwardLink
; Link
!= &Handle
->Protocols
; Link
=Link
->ForwardLink
) {
147 // If this protocol interface matches, remove it
149 Prot
= CR(Link
, PROTOCOL_INTERFACE
, Link
, PROTOCOL_INTERFACE_SIGNATURE
);
150 if (Prot
->Interface
== Interface
&& Prot
->Protocol
== ProtEntry
) {
160 Wrapper function to SmmInstallProtocolInterfaceNotify. 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 SmmInstallProtocolInterface (
176 IN OUT EFI_HANDLE
*UserHandle
,
177 IN EFI_GUID
*Protocol
,
178 IN EFI_INTERFACE_TYPE InterfaceType
,
182 return SmmInstallProtocolInterfaceNotify (
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 SmmInstallProtocolInterfaceNotify (
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
, "SmmInstallProtocolInterface: %g %p\n", Protocol
, Interface
));
240 Status
= EFI_OUT_OF_RESOURCES
;
244 if (*UserHandle
!= NULL
) {
245 Status
= SmmHandleProtocol (*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
= SmmFindProtocolEntry (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
);
291 Status
= SmmValidateHandle (Handle
);
292 if (EFI_ERROR (Status
)) {
293 DEBUG((DEBUG_ERROR
, "SmmInstallProtocolInterface: input handle at 0x%x is invalid\n", Handle
));
299 // Each interface that is added must be unique
301 ASSERT (SmmFindProtocolInterface (Handle
, Protocol
, Interface
) == NULL
);
304 // Initialize the protocol interface structure
306 Prot
->Signature
= PROTOCOL_INTERFACE_SIGNATURE
;
307 Prot
->Handle
= Handle
;
308 Prot
->Protocol
= ProtEntry
;
309 Prot
->Interface
= Interface
;
312 // Add this protocol interface to the head of the supported
313 // protocol list for this handle
315 InsertHeadList (&Handle
->Protocols
, &Prot
->Link
);
318 // Add this protocol interface to the tail of the
321 InsertTailList (&ProtEntry
->Protocols
, &Prot
->ByProtocol
);
324 // Notify the notification list for this protocol
327 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
344 DEBUG((DEBUG_ERROR
, "SmmInstallProtocolInterface: %g %p failed with %r\n", Protocol
, Interface
, Status
));
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 SmmUninstallProtocolInterface (
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
= SmmValidateHandle (UserHandle
);
385 if (EFI_ERROR (Status
)) {
390 // Check that Protocol exists on UserHandle, and Interface matches the interface in the database
392 Prot
= SmmFindProtocolInterface (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
= SmmRemoveInterfaceFromProtocol (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
);
430 Locate a certain GUID protocol interface in a Handle's protocols.
432 @param UserHandle The handle to obtain the protocol interface on
433 @param Protocol The GUID of the protocol
435 @return The requested protocol interface for the handle
439 SmmGetProtocolInterface (
440 IN EFI_HANDLE UserHandle
,
441 IN EFI_GUID
*Protocol
445 PROTOCOL_ENTRY
*ProtEntry
;
446 PROTOCOL_INTERFACE
*Prot
;
450 Status
= SmmValidateHandle (UserHandle
);
451 if (EFI_ERROR (Status
)) {
455 Handle
= (IHANDLE
*)UserHandle
;
458 // Look at each protocol interface for a match
460 for (Link
= Handle
->Protocols
.ForwardLink
; Link
!= &Handle
->Protocols
; Link
= Link
->ForwardLink
) {
461 Prot
= CR(Link
, PROTOCOL_INTERFACE
, Link
, PROTOCOL_INTERFACE_SIGNATURE
);
462 ProtEntry
= Prot
->Protocol
;
463 if (CompareGuid (&ProtEntry
->ProtocolID
, Protocol
)) {
471 Queries a handle to determine if it supports a specified protocol.
473 @param UserHandle The handle being queried.
474 @param Protocol The published unique identifier of the protocol.
475 @param Interface Supplies the address where a pointer to the
476 corresponding Protocol Interface is returned.
478 @retval EFI_SUCCESS The interface information for the specified protocol was returned.
479 @retval EFI_UNSUPPORTED The device does not support the specified protocol.
480 @retval EFI_INVALID_PARAMETER Handle is not a valid EFI_HANDLE..
481 @retval EFI_INVALID_PARAMETER Protocol is NULL.
482 @retval EFI_INVALID_PARAMETER Interface is NULL.
488 IN EFI_HANDLE UserHandle
,
489 IN EFI_GUID
*Protocol
,
494 PROTOCOL_INTERFACE
*Prot
;
497 // Check for invalid Protocol
499 if (Protocol
== NULL
) {
500 return EFI_INVALID_PARAMETER
;
504 // Check for invalid Interface
506 if (Interface
== NULL
) {
507 return EFI_INVALID_PARAMETER
;
513 // Check for invalid UserHandle
515 Status
= SmmValidateHandle (UserHandle
);
516 if (EFI_ERROR (Status
)) {
521 // Look at each protocol interface for a match
523 Prot
= SmmGetProtocolInterface (UserHandle
, Protocol
);
525 return EFI_UNSUPPORTED
;
529 // This is the protocol interface entry for this protocol
531 *Interface
= Prot
->Interface
;