2 SMM handle & protocol handling.
4 Copyright (c) 2009 - 2010, 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
);
292 Status
= SmmValidateHandle (Handle
);
293 if (EFI_ERROR (Status
)) {
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
);
328 Status
= EFI_SUCCESS
;
331 if (!EFI_ERROR (Status
)) {
333 // Return the new handle back to the caller
335 *UserHandle
= Handle
;
338 // There was an error, clean up
348 Uninstalls all instances of a protocol:interfacer from a handle.
349 If the last protocol interface is remove from the handle, the
352 @param UserHandle The handle to remove the protocol handler from
353 @param Protocol The protocol, of protocol:interface, to remove
354 @param Interface The interface, of protocol:interface, to remove
356 @retval EFI_INVALID_PARAMETER Protocol is NULL.
357 @retval EFI_SUCCESS Protocol interface successfully uninstalled.
362 SmmUninstallProtocolInterface (
363 IN EFI_HANDLE UserHandle
,
364 IN EFI_GUID
*Protocol
,
370 PROTOCOL_INTERFACE
*Prot
;
373 // Check that Protocol is valid
375 if (Protocol
== NULL
) {
376 return EFI_INVALID_PARAMETER
;
380 // Check that UserHandle is a valid handle
382 Status
= SmmValidateHandle (UserHandle
);
383 if (EFI_ERROR (Status
)) {
388 // Check that Protocol exists on UserHandle, and Interface matches the interface in the database
390 Prot
= SmmFindProtocolInterface (UserHandle
, Protocol
, Interface
);
392 return EFI_NOT_FOUND
;
396 // Remove the protocol interface from the protocol
398 Status
= EFI_NOT_FOUND
;
399 Handle
= (IHANDLE
*)UserHandle
;
400 Prot
= SmmRemoveInterfaceFromProtocol (Handle
, Protocol
, Interface
);
404 // Remove the protocol interface from the handle
406 RemoveEntryList (&Prot
->Link
);
413 Status
= EFI_SUCCESS
;
417 // If there are no more handlers for the handle, free the handle
419 if (IsListEmpty (&Handle
->Protocols
)) {
420 Handle
->Signature
= 0;
421 RemoveEntryList (&Handle
->AllHandles
);
428 Locate a certain GUID protocol interface in a Handle's protocols.
430 @param UserHandle The handle to obtain the protocol interface on
431 @param Protocol The GUID of the protocol
433 @return The requested protocol interface for the handle
437 SmmGetProtocolInterface (
438 IN EFI_HANDLE UserHandle
,
439 IN EFI_GUID
*Protocol
443 PROTOCOL_ENTRY
*ProtEntry
;
444 PROTOCOL_INTERFACE
*Prot
;
448 Status
= SmmValidateHandle (UserHandle
);
449 if (EFI_ERROR (Status
)) {
453 Handle
= (IHANDLE
*)UserHandle
;
456 // Look at each protocol interface for a match
458 for (Link
= Handle
->Protocols
.ForwardLink
; Link
!= &Handle
->Protocols
; Link
= Link
->ForwardLink
) {
459 Prot
= CR(Link
, PROTOCOL_INTERFACE
, Link
, PROTOCOL_INTERFACE_SIGNATURE
);
460 ProtEntry
= Prot
->Protocol
;
461 if (CompareGuid (&ProtEntry
->ProtocolID
, Protocol
)) {
469 Queries a handle to determine if it supports a specified protocol.
471 @param UserHandle The handle being queried.
472 @param Protocol The published unique identifier of the protocol.
473 @param Interface Supplies the address where a pointer to the
474 corresponding Protocol Interface is returned.
476 @retval EFI_SUCCESS The interface information for the specified protocol was returned.
477 @retval EFI_UNSUPPORTED The device does not support the specified protocol.
478 @retval EFI_INVALID_PARAMETER Handle is not a valid EFI_HANDLE..
479 @retval EFI_INVALID_PARAMETER Protocol is NULL.
480 @retval EFI_INVALID_PARAMETER Interface is NULL.
486 IN EFI_HANDLE UserHandle
,
487 IN EFI_GUID
*Protocol
,
492 PROTOCOL_INTERFACE
*Prot
;
495 // Check for invalid Protocol
497 if (Protocol
== NULL
) {
498 return EFI_INVALID_PARAMETER
;
502 // Check for invalid Interface
504 if (Interface
== NULL
) {
505 return EFI_INVALID_PARAMETER
;
511 // Check for invalid UserHandle
513 Status
= SmmValidateHandle (UserHandle
);
514 if (EFI_ERROR (Status
)) {
519 // Look at each protocol interface for a match
521 Prot
= SmmGetProtocolInterface (UserHandle
, Protocol
);
523 return EFI_UNSUPPORTED
;
527 // This is the protocol interface entry for this protocol
529 *Interface
= Prot
->Interface
;