]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Core/PiSmmCore/Notify.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[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 ProtEntry = Prot->Protocol;
58
59 //
60 // If there's a protocol notify location pointing to this entry, back it up one
61 //
62 for (Link = ProtEntry->Notify.ForwardLink; Link != &ProtEntry->Notify; Link = Link->ForwardLink) {
63 ProtNotify = CR (Link, PROTOCOL_NOTIFY, Link, PROTOCOL_NOTIFY_SIGNATURE);
64
65 if (ProtNotify->Position == &Prot->ByProtocol) {
66 ProtNotify->Position = Prot->ByProtocol.BackLink;
67 }
68 }
69
70 //
71 // Remove the protocol interface entry
72 //
73 RemoveEntryList (&Prot->ByProtocol);
74 }
75
76 return Prot;
77 }
78
79 /**
80 Add a new protocol notification record for the request protocol.
81
82 @param Protocol The requested protocol to add the notify
83 registration
84 @param Function Points to the notification function
85 @param Registration Returns the registration record
86
87 @retval EFI_SUCCESS Successfully returned the registration record
88 that has been added or unhooked
89 @retval EFI_INVALID_PARAMETER Protocol is NULL or Registration is NULL
90 @retval EFI_OUT_OF_RESOURCES Not enough memory resource to finish the request
91 @retval EFI_NOT_FOUND If the registration is not found when Function == NULL
92
93 **/
94 EFI_STATUS
95 EFIAPI
96 SmmRegisterProtocolNotify (
97 IN CONST EFI_GUID *Protocol,
98 IN EFI_SMM_NOTIFY_FN Function,
99 OUT VOID **Registration
100 )
101 {
102 PROTOCOL_ENTRY *ProtEntry;
103 PROTOCOL_NOTIFY *ProtNotify;
104 LIST_ENTRY *Link;
105 EFI_STATUS Status;
106
107 if ((Protocol == NULL) || (Registration == NULL)) {
108 return EFI_INVALID_PARAMETER;
109 }
110
111 if (Function == NULL) {
112 //
113 // Get the protocol entry per Protocol
114 //
115 ProtEntry = SmmFindProtocolEntry ((EFI_GUID *)Protocol, FALSE);
116 if (ProtEntry != NULL) {
117 ProtNotify = (PROTOCOL_NOTIFY *)*Registration;
118 for (Link = ProtEntry->Notify.ForwardLink;
119 Link != &ProtEntry->Notify;
120 Link = Link->ForwardLink)
121 {
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 //
138 // If the registration is not found
139 //
140 return EFI_NOT_FOUND;
141 }
142
143 ProtNotify = NULL;
144
145 //
146 // Get the protocol entry to add the notification too
147 //
148 ProtEntry = SmmFindProtocolEntry ((EFI_GUID *)Protocol, TRUE);
149 if (ProtEntry != NULL) {
150 //
151 // Find whether notification already exist
152 //
153 for (Link = ProtEntry->Notify.ForwardLink;
154 Link != &ProtEntry->Notify;
155 Link = Link->ForwardLink)
156 {
157 ProtNotify = CR (Link, PROTOCOL_NOTIFY, Link, PROTOCOL_NOTIFY_SIGNATURE);
158 if (CompareGuid (&ProtNotify->Protocol->ProtocolID, Protocol) &&
159 (ProtNotify->Function == Function))
160 {
161 //
162 // Notification already exist
163 //
164 *Registration = ProtNotify;
165
166 return EFI_SUCCESS;
167 }
168 }
169
170 //
171 // Allocate a new notification record
172 //
173 ProtNotify = AllocatePool (sizeof (PROTOCOL_NOTIFY));
174 if (ProtNotify != NULL) {
175 ProtNotify->Signature = PROTOCOL_NOTIFY_SIGNATURE;
176 ProtNotify->Protocol = ProtEntry;
177 ProtNotify->Function = Function;
178 //
179 // Start at the ending
180 //
181 ProtNotify->Position = ProtEntry->Protocols.BackLink;
182
183 InsertTailList (&ProtEntry->Notify, &ProtNotify->Link);
184 }
185 }
186
187 //
188 // Done. If we have a protocol notify entry, then return it.
189 // Otherwise, we must have run out of resources trying to add one
190 //
191 Status = EFI_OUT_OF_RESOURCES;
192 if (ProtNotify != NULL) {
193 *Registration = ProtNotify;
194 Status = EFI_SUCCESS;
195 }
196
197 return Status;
198 }