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