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