4 Copyright (c) 2009 - 2013, 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 // MM_HANDLER_STATE_NOTIFIER
23 // MM_HANDLER - used for each MM handler
26 #define MMI_ENTRY_SIGNATURE SIGNATURE_32('m','m','i','e')
30 LIST_ENTRY AllEntries
; // All entries
32 EFI_GUID HandlerType
; // Type of interrupt
33 LIST_ENTRY MmiHandlers
; // All handlers
36 #define MMI_HANDLER_SIGNATURE SIGNATURE_32('m','m','i','h')
40 LIST_ENTRY Link
; // Link on MMI_ENTRY.MmiHandlers
41 EFI_MM_HANDLER_ENTRY_POINT Handler
; // The mm handler's entry point
45 LIST_ENTRY mRootMmiHandlerList
= INITIALIZE_LIST_HEAD_VARIABLE (mRootMmiHandlerList
);
46 LIST_ENTRY mMmiEntryList
= INITIALIZE_LIST_HEAD_VARIABLE (mMmiEntryList
);
49 Finds the MMI entry for the requested handler type.
51 @param HandlerType The type of the interrupt
52 @param Create Create a new entry if not found
60 IN EFI_GUID
*HandlerType
,
69 // Search the MMI entry list for the matching GUID
72 for (Link
= mMmiEntryList
.ForwardLink
;
73 Link
!= &mMmiEntryList
;
74 Link
= Link
->ForwardLink
) {
76 Item
= CR (Link
, MMI_ENTRY
, AllEntries
, MMI_ENTRY_SIGNATURE
);
77 if (CompareGuid (&Item
->HandlerType
, HandlerType
)) {
79 // This is the MMI entry
87 // If the protocol entry was not found and Create is TRUE, then
88 // allocate a new entry
90 if ((MmiEntry
== NULL
) && Create
) {
91 MmiEntry
= AllocatePool (sizeof (MMI_ENTRY
));
92 if (MmiEntry
!= NULL
) {
94 // Initialize new MMI entry structure
96 MmiEntry
->Signature
= MMI_ENTRY_SIGNATURE
;
97 CopyGuid ((VOID
*)&MmiEntry
->HandlerType
, HandlerType
);
98 InitializeListHead (&MmiEntry
->MmiHandlers
);
101 // Add it to MMI entry list
103 InsertTailList (&mMmiEntryList
, &MmiEntry
->AllEntries
);
110 Manage MMI of a particular type.
112 @param HandlerType Points to the handler type or NULL for root MMI handlers.
113 @param Context Points to an optional context buffer.
114 @param CommBuffer Points to the optional communication buffer.
115 @param CommBufferSize Points to the size of the optional communication buffer.
117 @retval EFI_WARN_INTERRUPT_SOURCE_PENDING Interrupt source was processed successfully but not quiesced.
118 @retval EFI_INTERRUPT_PENDING One or more MMI sources could not be quiesced.
119 @retval EFI_NOT_FOUND Interrupt source was not handled or quiesced.
120 @retval EFI_SUCCESS Interrupt source was handled and quiesced.
126 IN CONST EFI_GUID
*HandlerType
,
127 IN CONST VOID
*Context OPTIONAL
,
128 IN OUT VOID
*CommBuffer OPTIONAL
,
129 IN OUT UINTN
*CommBufferSize OPTIONAL
135 MMI_HANDLER
*MmiHandler
;
136 BOOLEAN SuccessReturn
;
139 Status
= EFI_NOT_FOUND
;
140 SuccessReturn
= FALSE
;
141 if (HandlerType
== NULL
) {
146 Head
= &mRootMmiHandlerList
;
149 // Non-root MMI handler
151 MmiEntry
= MmCoreFindMmiEntry ((EFI_GUID
*) HandlerType
, FALSE
);
152 if (MmiEntry
== NULL
) {
154 // There is no handler registered for this interrupt source
159 Head
= &MmiEntry
->MmiHandlers
;
162 for (Link
= Head
->ForwardLink
; Link
!= Head
; Link
= Link
->ForwardLink
) {
163 MmiHandler
= CR (Link
, MMI_HANDLER
, Link
, MMI_HANDLER_SIGNATURE
);
165 Status
= MmiHandler
->Handler (
166 (EFI_HANDLE
) MmiHandler
,
173 case EFI_INTERRUPT_PENDING
:
175 // If a handler returns EFI_INTERRUPT_PENDING and HandlerType is not NULL then
176 // no additional handlers will be processed and EFI_INTERRUPT_PENDING will be returned.
178 if (HandlerType
!= NULL
) {
179 return EFI_INTERRUPT_PENDING
;
185 // If at least one of the handlers returns EFI_SUCCESS then the function will return
186 // EFI_SUCCESS. If a handler returns EFI_SUCCESS and HandlerType is not NULL then no
187 // additional handlers will be processed.
189 if (HandlerType
!= NULL
) {
192 SuccessReturn
= TRUE
;
195 case EFI_WARN_INTERRUPT_SOURCE_QUIESCED
:
197 // If at least one of the handlers returns EFI_WARN_INTERRUPT_SOURCE_QUIESCED
198 // then the function will return EFI_SUCCESS.
200 SuccessReturn
= TRUE
;
203 case EFI_WARN_INTERRUPT_SOURCE_PENDING
:
205 // If all the handlers returned EFI_WARN_INTERRUPT_SOURCE_PENDING
206 // then EFI_WARN_INTERRUPT_SOURCE_PENDING will be returned.
212 // Unexpected status code returned.
220 Status
= EFI_SUCCESS
;
227 Registers a handler to execute within MM.
229 @param Handler Handler service funtion pointer.
230 @param HandlerType Points to the handler type or NULL for root MMI handlers.
231 @param DispatchHandle On return, contains a unique handle which can be used to later unregister the handler function.
233 @retval EFI_SUCCESS Handler register success.
234 @retval EFI_INVALID_PARAMETER Handler or DispatchHandle is NULL.
240 IN EFI_MM_HANDLER_ENTRY_POINT Handler
,
241 IN CONST EFI_GUID
*HandlerType OPTIONAL
,
242 OUT EFI_HANDLE
*DispatchHandle
245 MMI_HANDLER
*MmiHandler
;
249 if (Handler
== NULL
|| DispatchHandle
== NULL
) {
250 return EFI_INVALID_PARAMETER
;
253 MmiHandler
= AllocateZeroPool (sizeof (MMI_HANDLER
));
254 if (MmiHandler
== NULL
) {
255 return EFI_OUT_OF_RESOURCES
;
258 MmiHandler
->Signature
= MMI_HANDLER_SIGNATURE
;
259 MmiHandler
->Handler
= Handler
;
261 if (HandlerType
== NULL
) {
263 // This is root MMI handler
266 List
= &mRootMmiHandlerList
;
269 // None root MMI handler
271 MmiEntry
= MmCoreFindMmiEntry ((EFI_GUID
*) HandlerType
, TRUE
);
272 if (MmiEntry
== NULL
) {
273 return EFI_OUT_OF_RESOURCES
;
276 List
= &MmiEntry
->MmiHandlers
;
279 MmiHandler
->MmiEntry
= MmiEntry
;
280 InsertTailList (List
, &MmiHandler
->Link
);
282 *DispatchHandle
= (EFI_HANDLE
) MmiHandler
;
288 Unregister a handler in MM.
290 @param DispatchHandle The handle that was specified when the handler was registered.
292 @retval EFI_SUCCESS Handler function was successfully unregistered.
293 @retval EFI_INVALID_PARAMETER DispatchHandle does not refer to a valid handle.
298 MmiHandlerUnRegister (
299 IN EFI_HANDLE DispatchHandle
302 MMI_HANDLER
*MmiHandler
;
305 MmiHandler
= (MMI_HANDLER
*) DispatchHandle
;
307 if (MmiHandler
== NULL
) {
308 return EFI_INVALID_PARAMETER
;
311 if (MmiHandler
->Signature
!= MMI_HANDLER_SIGNATURE
) {
312 return EFI_INVALID_PARAMETER
;
315 MmiEntry
= MmiHandler
->MmiEntry
;
317 RemoveEntryList (&MmiHandler
->Link
);
318 FreePool (MmiHandler
);
320 if (MmiEntry
== NULL
) {
322 // This is root MMI handler
327 if (IsListEmpty (&MmiEntry
->MmiHandlers
)) {
329 // No handler registered for this interrupt now, remove the MMI_ENTRY
331 RemoveEntryList (&MmiEntry
->AllEntries
);