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 This program and the accompanying materials are licensed and made available
7 under the terms and conditions of the BSD License which accompanies this
8 distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
16 #include "StandaloneMmCore.h"
19 // mProtocolDatabase - A list of all protocols in the system. (simple list for now)
20 // gHandleList - A list of all the handles in the system
22 LIST_ENTRY mProtocolDatabase
= INITIALIZE_LIST_HEAD_VARIABLE (mProtocolDatabase
);
23 LIST_ENTRY gHandleList
= INITIALIZE_LIST_HEAD_VARIABLE (gHandleList
);
26 Check whether a handle is a valid EFI_HANDLE
28 @param UserHandle The handle to check
30 @retval EFI_INVALID_PARAMETER The handle is NULL or not a valid EFI_HANDLE.
31 @retval EFI_SUCCESS The handle is valid EFI_HANDLE.
36 IN EFI_HANDLE UserHandle
41 Handle
= (IHANDLE
*)UserHandle
;
43 return EFI_INVALID_PARAMETER
;
45 if (Handle
->Signature
!= EFI_HANDLE_SIGNATURE
) {
46 return EFI_INVALID_PARAMETER
;
52 Finds the protocol entry for the requested protocol.
54 @param Protocol The ID of the protocol
55 @param Create Create a new entry if not found
57 @return Protocol entry
62 IN EFI_GUID
*Protocol
,
68 PROTOCOL_ENTRY
*ProtEntry
;
71 // Search the database for the matching GUID
75 for (Link
= mProtocolDatabase
.ForwardLink
;
76 Link
!= &mProtocolDatabase
;
77 Link
= Link
->ForwardLink
) {
79 Item
= CR (Link
, PROTOCOL_ENTRY
, AllEntries
, PROTOCOL_ENTRY_SIGNATURE
);
80 if (CompareGuid (&Item
->ProtocolID
, Protocol
)) {
82 // This is the protocol entry
90 // If the protocol entry was not found and Create is TRUE, then
91 // allocate a new entry
93 if ((ProtEntry
== NULL
) && Create
) {
94 ProtEntry
= AllocatePool (sizeof(PROTOCOL_ENTRY
));
95 if (ProtEntry
!= NULL
) {
97 // Initialize new protocol entry structure
99 ProtEntry
->Signature
= PROTOCOL_ENTRY_SIGNATURE
;
100 CopyGuid ((VOID
*)&ProtEntry
->ProtocolID
, Protocol
);
101 InitializeListHead (&ProtEntry
->Protocols
);
102 InitializeListHead (&ProtEntry
->Notify
);
105 // Add it to protocol database
107 InsertTailList (&mProtocolDatabase
, &ProtEntry
->AllEntries
);
114 Finds the protocol instance for the requested handle and protocol.
115 Note: This function doesn't do parameters checking, it's caller's responsibility
116 to pass in valid parameters.
118 @param Handle The handle to search the protocol on
119 @param Protocol GUID of the protocol
120 @param Interface The interface for the protocol being searched
122 @return Protocol instance (NULL: Not found)
126 MmFindProtocolInterface (
128 IN EFI_GUID
*Protocol
,
132 PROTOCOL_INTERFACE
*Prot
;
133 PROTOCOL_ENTRY
*ProtEntry
;
139 // Lookup the protocol entry for this protocol ID
141 ProtEntry
= MmFindProtocolEntry (Protocol
, FALSE
);
142 if (ProtEntry
!= NULL
) {
144 // Look at each protocol interface for any matches
146 for (Link
= Handle
->Protocols
.ForwardLink
; Link
!= &Handle
->Protocols
; Link
=Link
->ForwardLink
) {
148 // If this protocol interface matches, remove it
150 Prot
= CR (Link
, PROTOCOL_INTERFACE
, Link
, PROTOCOL_INTERFACE_SIGNATURE
);
151 if (Prot
->Interface
== Interface
&& Prot
->Protocol
== ProtEntry
) {
161 Wrapper function to MmInstallProtocolInterfaceNotify. This is the public API which
162 Calls the private one which contains a BOOLEAN parameter for notifications
164 @param UserHandle The handle to install the protocol handler on,
165 or NULL if a new handle is to be allocated
166 @param Protocol The protocol to add to the handle
167 @param InterfaceType Indicates whether Interface is supplied in
169 @param Interface The interface for the protocol being added
176 MmInstallProtocolInterface (
177 IN OUT EFI_HANDLE
*UserHandle
,
178 IN EFI_GUID
*Protocol
,
179 IN EFI_INTERFACE_TYPE InterfaceType
,
183 return MmInstallProtocolInterfaceNotify (
193 Installs a protocol interface into the boot services environment.
195 @param UserHandle The handle to install the protocol handler on,
196 or NULL if a new handle is to be allocated
197 @param Protocol The protocol to add to the handle
198 @param InterfaceType Indicates whether Interface is supplied in
200 @param Interface The interface for the protocol being added
201 @param Notify indicates whether notify the notification list
204 @retval EFI_INVALID_PARAMETER Invalid parameter
205 @retval EFI_OUT_OF_RESOURCES No enough buffer to allocate
206 @retval EFI_SUCCESS Protocol interface successfully installed
210 MmInstallProtocolInterfaceNotify (
211 IN OUT EFI_HANDLE
*UserHandle
,
212 IN EFI_GUID
*Protocol
,
213 IN EFI_INTERFACE_TYPE InterfaceType
,
218 PROTOCOL_INTERFACE
*Prot
;
219 PROTOCOL_ENTRY
*ProtEntry
;
222 VOID
*ExistingInterface
;
225 // returns EFI_INVALID_PARAMETER if InterfaceType is invalid.
226 // Also added check for invalid UserHandle and Protocol pointers.
228 if (UserHandle
== NULL
|| Protocol
== NULL
) {
229 return EFI_INVALID_PARAMETER
;
232 if (InterfaceType
!= EFI_NATIVE_INTERFACE
) {
233 return EFI_INVALID_PARAMETER
;
237 // Print debug message
239 DEBUG ((DEBUG_LOAD
| DEBUG_INFO
, "MmInstallProtocolInterface: %g %p\n", Protocol
, Interface
));
241 Status
= EFI_OUT_OF_RESOURCES
;
245 if (*UserHandle
!= NULL
) {
246 Status
= MmHandleProtocol (*UserHandle
, Protocol
, (VOID
**)&ExistingInterface
);
247 if (!EFI_ERROR (Status
)) {
248 return EFI_INVALID_PARAMETER
;
253 // Lookup the Protocol Entry for the requested protocol
255 ProtEntry
= MmFindProtocolEntry (Protocol
, TRUE
);
256 if (ProtEntry
== NULL
) {
261 // Allocate a new protocol interface structure
263 Prot
= AllocateZeroPool (sizeof (PROTOCOL_INTERFACE
));
265 Status
= EFI_OUT_OF_RESOURCES
;
270 // If caller didn't supply a handle, allocate a new one
272 Handle
= (IHANDLE
*)*UserHandle
;
273 if (Handle
== NULL
) {
274 Handle
= AllocateZeroPool (sizeof (IHANDLE
));
275 if (Handle
== NULL
) {
276 Status
= EFI_OUT_OF_RESOURCES
;
281 // Initialize new handler structure
283 Handle
->Signature
= EFI_HANDLE_SIGNATURE
;
284 InitializeListHead (&Handle
->Protocols
);
287 // Add this handle to the list global list of all handles
290 InsertTailList (&gHandleList
, &Handle
->AllHandles
);
293 Status
= MmValidateHandle (Handle
);
294 if (EFI_ERROR (Status
)) {
299 // Each interface that is added must be unique
301 ASSERT (MmFindProtocolInterface (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 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
349 Uninstalls all instances of a protocol:interfacer from a handle.
350 If the last protocol interface is remove from the handle, the
353 @param UserHandle The handle to remove the protocol handler from
354 @param Protocol The protocol, of protocol:interface, to remove
355 @param Interface The interface, of protocol:interface, to remove
357 @retval EFI_INVALID_PARAMETER Protocol is NULL.
358 @retval EFI_SUCCESS Protocol interface successfully uninstalled.
363 MmUninstallProtocolInterface (
364 IN EFI_HANDLE UserHandle
,
365 IN EFI_GUID
*Protocol
,
371 PROTOCOL_INTERFACE
*Prot
;
374 // Check that Protocol is valid
376 if (Protocol
== NULL
) {
377 return EFI_INVALID_PARAMETER
;
381 // Check that UserHandle is a valid handle
383 Status
= MmValidateHandle (UserHandle
);
384 if (EFI_ERROR (Status
)) {
389 // Check that Protocol exists on UserHandle, and Interface matches the interface in the database
391 Prot
= MmFindProtocolInterface (UserHandle
, Protocol
, Interface
);
393 return EFI_NOT_FOUND
;
397 // Remove the protocol interface from the protocol
399 Status
= EFI_NOT_FOUND
;
400 Handle
= (IHANDLE
*)UserHandle
;
401 Prot
= MmRemoveInterfaceFromProtocol (Handle
, Protocol
, Interface
);
405 // Remove the protocol interface from the handle
407 RemoveEntryList (&Prot
->Link
);
414 Status
= EFI_SUCCESS
;
418 // If there are no more handlers for the handle, free the handle
420 if (IsListEmpty (&Handle
->Protocols
)) {
421 Handle
->Signature
= 0;
422 RemoveEntryList (&Handle
->AllHandles
);
429 Locate a certain GUID protocol interface in a Handle's protocols.
431 @param UserHandle The handle to obtain the protocol interface on
432 @param Protocol The GUID of the protocol
434 @return The requested protocol interface for the handle
438 MmGetProtocolInterface (
439 IN EFI_HANDLE UserHandle
,
440 IN EFI_GUID
*Protocol
444 PROTOCOL_ENTRY
*ProtEntry
;
445 PROTOCOL_INTERFACE
*Prot
;
449 Status
= MmValidateHandle (UserHandle
);
450 if (EFI_ERROR (Status
)) {
454 Handle
= (IHANDLE
*)UserHandle
;
457 // Look at each protocol interface for a match
459 for (Link
= Handle
->Protocols
.ForwardLink
; Link
!= &Handle
->Protocols
; Link
= Link
->ForwardLink
) {
460 Prot
= CR (Link
, PROTOCOL_INTERFACE
, Link
, PROTOCOL_INTERFACE_SIGNATURE
);
461 ProtEntry
= Prot
->Protocol
;
462 if (CompareGuid (&ProtEntry
->ProtocolID
, Protocol
)) {
470 Queries a handle to determine if it supports a specified protocol.
472 @param UserHandle The handle being queried.
473 @param Protocol The published unique identifier of the protocol.
474 @param Interface Supplies the address where a pointer to the
475 corresponding Protocol Interface is returned.
477 @retval EFI_SUCCESS The interface information for the specified protocol was returned.
478 @retval EFI_UNSUPPORTED The device does not support the specified protocol.
479 @retval EFI_INVALID_PARAMETER Handle is not a valid EFI_HANDLE..
480 @retval EFI_INVALID_PARAMETER Protocol is NULL.
481 @retval EFI_INVALID_PARAMETER Interface is NULL.
487 IN EFI_HANDLE UserHandle
,
488 IN EFI_GUID
*Protocol
,
493 PROTOCOL_INTERFACE
*Prot
;
496 // Check for invalid Protocol
498 if (Protocol
== NULL
) {
499 return EFI_INVALID_PARAMETER
;
503 // Check for invalid Interface
505 if (Interface
== NULL
) {
506 return EFI_INVALID_PARAMETER
;
512 // Check for invalid UserHandle
514 Status
= MmValidateHandle (UserHandle
);
515 if (EFI_ERROR (Status
)) {
520 // Look at each protocol interface for a match
522 Prot
= MmGetProtocolInterface (UserHandle
, Protocol
);
524 return EFI_UNSUPPORTED
;
528 // This is the protocol interface entry for this protocol
530 *Interface
= Prot
->Interface
;