]> git.proxmox.com Git - mirror_edk2.git/blob - StandaloneMmPkg/Core/Notify.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / StandaloneMmPkg / Core / Notify.c
1 /** @file
2 Support functions for UEFI protocol notification infrastructure.
3
4 Copyright (c) 2009 - 2015, Intel Corporation. All rights reserved.<BR>
5 Copyright (c) 2016 - 2018, ARM Limited. All rights reserved.<BR>
6 SPDX-License-Identifier: BSD-2-Clause-Patent
7
8 **/
9
10 #include "StandaloneMmCore.h"
11
12 /**
13 Signal event for every protocol in protocol entry.
14
15 @param Prot Protocol interface
16
17 **/
18 VOID
19 MmNotifyProtocol (
20 IN PROTOCOL_INTERFACE *Prot
21 )
22 {
23 PROTOCOL_ENTRY *ProtEntry;
24 PROTOCOL_NOTIFY *ProtNotify;
25 LIST_ENTRY *Link;
26
27 ProtEntry = Prot->Protocol;
28 for (Link = ProtEntry->Notify.ForwardLink; Link != &ProtEntry->Notify; Link = Link->ForwardLink) {
29 ProtNotify = CR (Link, PROTOCOL_NOTIFY, Link, PROTOCOL_NOTIFY_SIGNATURE);
30 ProtNotify->Function (&ProtEntry->ProtocolID, Prot->Interface, Prot->Handle);
31 }
32 }
33
34 /**
35 Removes Protocol from the protocol list (but not the handle list).
36
37 @param Handle The handle to remove protocol on.
38 @param Protocol GUID of the protocol to be moved
39 @param Interface The interface of the protocol
40
41 @return Protocol Entry
42
43 **/
44 PROTOCOL_INTERFACE *
45 MmRemoveInterfaceFromProtocol (
46 IN IHANDLE *Handle,
47 IN EFI_GUID *Protocol,
48 IN VOID *Interface
49 )
50 {
51 PROTOCOL_INTERFACE *Prot;
52 PROTOCOL_NOTIFY *ProtNotify;
53 PROTOCOL_ENTRY *ProtEntry;
54 LIST_ENTRY *Link;
55
56 Prot = MmFindProtocolInterface (Handle, Protocol, Interface);
57 if (Prot != NULL) {
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 MmRegisterProtocolNotify (
98 IN CONST EFI_GUID *Protocol,
99 IN EFI_MM_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 = MmFindProtocolEntry ((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 //
124 // Compare the notification record
125 //
126 if (ProtNotify == (CR (Link, PROTOCOL_NOTIFY, Link, PROTOCOL_NOTIFY_SIGNATURE))) {
127 //
128 // If Registration is an existing registration, then unhook it
129 //
130 ProtNotify->Signature = 0;
131 RemoveEntryList (&ProtNotify->Link);
132 FreePool (ProtNotify);
133 return EFI_SUCCESS;
134 }
135 }
136 }
137
138 //
139 // If the registration is not found
140 //
141 return EFI_NOT_FOUND;
142 }
143
144 ProtNotify = NULL;
145
146 //
147 // Get the protocol entry to add the notification too
148 //
149 ProtEntry = MmFindProtocolEntry ((EFI_GUID *)Protocol, TRUE);
150 if (ProtEntry != NULL) {
151 //
152 // Find whether notification already exist
153 //
154 for (Link = ProtEntry->Notify.ForwardLink;
155 Link != &ProtEntry->Notify;
156 Link = Link->ForwardLink)
157 {
158 ProtNotify = CR (Link, PROTOCOL_NOTIFY, Link, PROTOCOL_NOTIFY_SIGNATURE);
159 if (CompareGuid (&ProtNotify->Protocol->ProtocolID, Protocol) &&
160 (ProtNotify->Function == Function))
161 {
162 //
163 // Notification already exist
164 //
165 *Registration = ProtNotify;
166
167 return EFI_SUCCESS;
168 }
169 }
170
171 //
172 // Allocate a new notification record
173 //
174 ProtNotify = AllocatePool (sizeof (PROTOCOL_NOTIFY));
175 if (ProtNotify != NULL) {
176 ProtNotify->Signature = PROTOCOL_NOTIFY_SIGNATURE;
177 ProtNotify->Protocol = ProtEntry;
178 ProtNotify->Function = Function;
179 //
180 // Start at the ending
181 //
182 ProtNotify->Position = ProtEntry->Protocols.BackLink;
183
184 InsertTailList (&ProtEntry->Notify, &ProtNotify->Link);
185 }
186 }
187
188 //
189 // Done. If we have a protocol notify entry, then return it.
190 // Otherwise, we must have run out of resources trying to add one
191 //
192 Status = EFI_OUT_OF_RESOURCES;
193 if (ProtNotify != NULL) {
194 *Registration = ProtNotify;
195 Status = EFI_SUCCESS;
196 }
197
198 return Status;
199 }