]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Core/PiSmmCore/Notify.c
MdeModulePkg/Core: allow HeapGuard even before CpuArchProtocol installed
[mirror_edk2.git] / MdeModulePkg / Core / PiSmmCore / Notify.c
CommitLineData
e42e9404 1/** @file\r
2 Support functions for UEFI protocol notification infrastructure.\r
3\r
aeb4c944 4 Copyright (c) 2009 - 2015, Intel Corporation. All rights reserved.<BR>\r
e42e9404 5 This program and the accompanying materials are licensed and made available \r
6 under the terms and conditions of the BSD License which accompanies this \r
7 distribution. The full text of the license may be found at \r
8 http://opensource.org/licenses/bsd-license.php \r
9\r
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
12\r
13**/\r
14\r
15#include "PiSmmCore.h"\r
16\r
17/**\r
18 Signal event for every protocol in protocol entry.\r
19\r
20 @param Prot Protocol interface\r
21\r
22**/\r
23VOID\r
24SmmNotifyProtocol (\r
25 IN PROTOCOL_INTERFACE *Prot\r
26 )\r
27{\r
28 PROTOCOL_ENTRY *ProtEntry;\r
29 PROTOCOL_NOTIFY *ProtNotify;\r
30 LIST_ENTRY *Link;\r
31\r
32 ProtEntry = Prot->Protocol;\r
33 for (Link=ProtEntry->Notify.ForwardLink; Link != &ProtEntry->Notify; Link=Link->ForwardLink) {\r
34 ProtNotify = CR(Link, PROTOCOL_NOTIFY, Link, PROTOCOL_NOTIFY_SIGNATURE);\r
35 ProtNotify->Function (&ProtEntry->ProtocolID, Prot->Interface, Prot->Handle);\r
36 }\r
37}\r
38\r
39/**\r
40 Removes Protocol from the protocol list (but not the handle list).\r
41\r
42 @param Handle The handle to remove protocol on.\r
43 @param Protocol GUID of the protocol to be moved\r
44 @param Interface The interface of the protocol\r
45\r
46 @return Protocol Entry\r
47\r
48**/\r
49PROTOCOL_INTERFACE *\r
50SmmRemoveInterfaceFromProtocol (\r
51 IN IHANDLE *Handle,\r
52 IN EFI_GUID *Protocol,\r
53 IN VOID *Interface\r
54 )\r
55{\r
56 PROTOCOL_INTERFACE *Prot;\r
57 PROTOCOL_NOTIFY *ProtNotify;\r
58 PROTOCOL_ENTRY *ProtEntry;\r
59 LIST_ENTRY *Link;\r
60\r
61 Prot = SmmFindProtocolInterface (Handle, Protocol, Interface);\r
62 if (Prot != NULL) {\r
63\r
64 ProtEntry = Prot->Protocol;\r
65\r
66 //\r
67 // If there's a protocol notify location pointing to this entry, back it up one\r
68 //\r
69 for(Link = ProtEntry->Notify.ForwardLink; Link != &ProtEntry->Notify; Link=Link->ForwardLink) {\r
70 ProtNotify = CR(Link, PROTOCOL_NOTIFY, Link, PROTOCOL_NOTIFY_SIGNATURE);\r
71\r
72 if (ProtNotify->Position == &Prot->ByProtocol) {\r
73 ProtNotify->Position = Prot->ByProtocol.BackLink;\r
74 }\r
75 }\r
76\r
77 //\r
78 // Remove the protocol interface entry\r
79 //\r
80 RemoveEntryList (&Prot->ByProtocol);\r
81 }\r
82\r
83 return Prot;\r
84}\r
85\r
86/**\r
87 Add a new protocol notification record for the request protocol.\r
88\r
89 @param Protocol The requested protocol to add the notify\r
90 registration\r
91 @param Function Points to the notification function\r
92 @param Registration Returns the registration record\r
93\r
e42e9404 94 @retval EFI_SUCCESS Successfully returned the registration record\r
aeb4c944
JF
95 that has been added or unhooked\r
96 @retval EFI_INVALID_PARAMETER Protocol is NULL or Registration is NULL\r
50903aa5
JF
97 @retval EFI_OUT_OF_RESOURCES Not enough memory resource to finish the request\r
98 @retval EFI_NOT_FOUND If the registration is not found when Function == NULL\r
e42e9404 99\r
100**/\r
101EFI_STATUS\r
102EFIAPI\r
103SmmRegisterProtocolNotify (\r
104 IN CONST EFI_GUID *Protocol,\r
105 IN EFI_SMM_NOTIFY_FN Function,\r
106 OUT VOID **Registration\r
107 )\r
108{\r
109 PROTOCOL_ENTRY *ProtEntry;\r
110 PROTOCOL_NOTIFY *ProtNotify;\r
111 LIST_ENTRY *Link;\r
112 EFI_STATUS Status;\r
113\r
50903aa5 114 if (Protocol == NULL || Registration == NULL) {\r
e42e9404 115 return EFI_INVALID_PARAMETER;\r
116 }\r
117\r
50903aa5
JF
118 if (Function == NULL) {\r
119 //\r
120 // Get the protocol entry per Protocol\r
121 //\r
122 ProtEntry = SmmFindProtocolEntry ((EFI_GUID *) Protocol, FALSE);\r
123 if (ProtEntry != NULL) {\r
124 ProtNotify = (PROTOCOL_NOTIFY * )*Registration;\r
125 for (Link = ProtEntry->Notify.ForwardLink;\r
126 Link != &ProtEntry->Notify;\r
127 Link = Link->ForwardLink) {\r
128 //\r
129 // Compare the notification record \r
130 //\r
131 if (ProtNotify == (CR(Link, PROTOCOL_NOTIFY, Link, PROTOCOL_NOTIFY_SIGNATURE))){\r
132 //\r
133 // If Registration is an existing registration, then unhook it\r
134 //\r
135 ProtNotify->Signature = 0;\r
136 RemoveEntryList (&ProtNotify->Link);\r
137 FreePool (ProtNotify);\r
138 return EFI_SUCCESS;\r
139 }\r
140 }\r
141 }\r
142 //\r
143 // If the registration is not found\r
144 //\r
145 return EFI_NOT_FOUND;\r
146 } \r
147\r
e42e9404 148 ProtNotify = NULL;\r
149\r
150 //\r
151 // Get the protocol entry to add the notification too\r
152 //\r
153 ProtEntry = SmmFindProtocolEntry ((EFI_GUID *) Protocol, TRUE);\r
154 if (ProtEntry != NULL) {\r
155 //\r
156 // Find whether notification already exist\r
157 //\r
158 for (Link = ProtEntry->Notify.ForwardLink;\r
159 Link != &ProtEntry->Notify;\r
160 Link = Link->ForwardLink) {\r
161\r
162 ProtNotify = CR(Link, PROTOCOL_NOTIFY, Link, PROTOCOL_NOTIFY_SIGNATURE);\r
163 if (CompareGuid (&ProtNotify->Protocol->ProtocolID, Protocol) &&\r
164 (ProtNotify->Function == Function)) {\r
165\r
166 //\r
167 // Notification already exist\r
168 //\r
169 *Registration = ProtNotify;\r
170\r
171 return EFI_SUCCESS;\r
172 }\r
173 }\r
174\r
175 //\r
176 // Allocate a new notification record\r
177 //\r
178 ProtNotify = AllocatePool (sizeof(PROTOCOL_NOTIFY));\r
179 if (ProtNotify != NULL) {\r
180 ProtNotify->Signature = PROTOCOL_NOTIFY_SIGNATURE;\r
181 ProtNotify->Protocol = ProtEntry;\r
182 ProtNotify->Function = Function;\r
183 //\r
184 // Start at the ending\r
185 //\r
186 ProtNotify->Position = ProtEntry->Protocols.BackLink;\r
187\r
188 InsertTailList (&ProtEntry->Notify, &ProtNotify->Link);\r
189 }\r
190 }\r
191\r
192 //\r
193 // Done. If we have a protocol notify entry, then return it.\r
194 // Otherwise, we must have run out of resources trying to add one\r
195 //\r
196 Status = EFI_OUT_OF_RESOURCES;\r
197 if (ProtNotify != NULL) {\r
198 *Registration = ProtNotify;\r
199 Status = EFI_SUCCESS;\r
200 }\r
201 return Status;\r
202}\r