]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Core/Dxe/DxeMain/DxeProtocolNotify.c
MdeModulePkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / MdeModulePkg / Core / Dxe / DxeMain / DxeProtocolNotify.c
1 /** @file
2 This file deals with Architecture Protocol (AP) registration in
3 the Dxe Core. The mArchProtocols[] array represents a list of
4 events that represent the Architectural Protocols.
5
6 Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
7 SPDX-License-Identifier: BSD-2-Clause-Patent
8
9 **/
10
11 #include "DxeMain.h"
12
13 //
14 // DXE Core Global Variables for all of the Architectural Protocols.
15 // If a protocol is installed mArchProtocols[].Present will be TRUE.
16 //
17 // CoreNotifyOnArchProtocolInstallation () fills in mArchProtocols[].Event
18 // and mArchProtocols[].Registration as it creates events for every array
19 // entry.
20 //
21 EFI_CORE_PROTOCOL_NOTIFY_ENTRY mArchProtocols[] = {
22 { &gEfiSecurityArchProtocolGuid, (VOID **)&gSecurity, NULL, NULL, FALSE },
23 { &gEfiCpuArchProtocolGuid, (VOID **)&gCpu, NULL, NULL, FALSE },
24 { &gEfiMetronomeArchProtocolGuid, (VOID **)&gMetronome, NULL, NULL, FALSE },
25 { &gEfiTimerArchProtocolGuid, (VOID **)&gTimer, NULL, NULL, FALSE },
26 { &gEfiBdsArchProtocolGuid, (VOID **)&gBds, NULL, NULL, FALSE },
27 { &gEfiWatchdogTimerArchProtocolGuid, (VOID **)&gWatchdogTimer, NULL, NULL, FALSE },
28 { &gEfiRuntimeArchProtocolGuid, (VOID **)&gRuntime, NULL, NULL, FALSE },
29 { &gEfiVariableArchProtocolGuid, (VOID **)NULL, NULL, NULL, FALSE },
30 { &gEfiVariableWriteArchProtocolGuid, (VOID **)NULL, NULL, NULL, FALSE },
31 { &gEfiCapsuleArchProtocolGuid, (VOID **)NULL, NULL, NULL, FALSE },
32 { &gEfiMonotonicCounterArchProtocolGuid, (VOID **)NULL, NULL, NULL, FALSE },
33 { &gEfiResetArchProtocolGuid, (VOID **)NULL, NULL, NULL, FALSE },
34 { &gEfiRealTimeClockArchProtocolGuid, (VOID **)NULL, NULL, NULL, FALSE },
35 { NULL, (VOID **)NULL, NULL, NULL, FALSE }
36 };
37
38 //
39 // Optional protocols that the DXE Core will use if they are present
40 //
41 EFI_CORE_PROTOCOL_NOTIFY_ENTRY mOptionalProtocols[] = {
42 { &gEfiSecurity2ArchProtocolGuid, (VOID **)&gSecurity2, NULL, NULL, FALSE },
43 { &gEfiSmmBase2ProtocolGuid, (VOID **)&gSmmBase2, NULL, NULL, FALSE },
44 { NULL, (VOID **)NULL, NULL, NULL, FALSE }
45 };
46
47 //
48 // Following is needed to display missing architectural protocols in debug builds
49 //
50 typedef struct {
51 EFI_GUID *ProtocolGuid;
52 CHAR8 *GuidString;
53 } GUID_TO_STRING_PROTOCOL_ENTRY;
54
55 GLOBAL_REMOVE_IF_UNREFERENCED CONST GUID_TO_STRING_PROTOCOL_ENTRY mMissingProtocols[] = {
56 { &gEfiSecurityArchProtocolGuid, "Security" },
57 { &gEfiCpuArchProtocolGuid, "CPU" },
58 { &gEfiMetronomeArchProtocolGuid, "Metronome" },
59 { &gEfiTimerArchProtocolGuid, "Timer" },
60 { &gEfiBdsArchProtocolGuid, "Bds" },
61 { &gEfiWatchdogTimerArchProtocolGuid, "Watchdog Timer" },
62 { &gEfiRuntimeArchProtocolGuid, "Runtime" },
63 { &gEfiVariableArchProtocolGuid, "Variable" },
64 { &gEfiVariableWriteArchProtocolGuid, "Variable Write" },
65 { &gEfiCapsuleArchProtocolGuid, "Capsule" },
66 { &gEfiMonotonicCounterArchProtocolGuid, "Monotonic Counter" },
67 { &gEfiResetArchProtocolGuid, "Reset" },
68 { &gEfiRealTimeClockArchProtocolGuid, "Real Time Clock" },
69 { NULL, "" }
70 };
71
72 /**
73 Return TRUE if all AP services are available.
74
75 @retval EFI_SUCCESS All AP services are available
76 @retval EFI_NOT_FOUND At least one AP service is not available
77
78 **/
79 EFI_STATUS
80 CoreAllEfiServicesAvailable (
81 VOID
82 )
83 {
84 EFI_CORE_PROTOCOL_NOTIFY_ENTRY *Entry;
85
86 for (Entry = mArchProtocols; Entry->ProtocolGuid != NULL; Entry++) {
87 if (!Entry->Present) {
88 return EFI_NOT_FOUND;
89 }
90 }
91 return EFI_SUCCESS;
92 }
93
94
95 /**
96 Notification event handler registered by CoreNotifyOnArchProtocolInstallation ().
97 This notify function is registered for every architectural protocol. This handler
98 updates mArchProtocol[] array entry with protocol instance data and sets it's
99 present flag to TRUE. If any constructor is required it is executed. The EFI
100 System Table headers are updated.
101
102 @param Event The Event that is being processed, not used.
103 @param Context Event Context, not used.
104
105 **/
106 VOID
107 EFIAPI
108 GenericProtocolNotify (
109 IN EFI_EVENT Event,
110 IN VOID *Context
111 )
112 {
113 EFI_STATUS Status;
114 EFI_CORE_PROTOCOL_NOTIFY_ENTRY *Entry;
115 VOID *Protocol;
116 LIST_ENTRY *Link;
117 LIST_ENTRY TempLinkNode;
118
119 Protocol = NULL;
120
121 //
122 // Get Entry from Context
123 //
124 Entry = (EFI_CORE_PROTOCOL_NOTIFY_ENTRY *)Context;
125
126 //
127 // See if the expected protocol is present in the handle database
128 //
129 Status = CoreLocateProtocol (Entry->ProtocolGuid, Entry->Registration, &Protocol);
130 if (EFI_ERROR (Status)) {
131 return;
132 }
133
134 //
135 // Mark the protocol as present
136 //
137 Entry->Present = TRUE;
138
139 //
140 // Update protocol global variable if one exists. Entry->Protocol points to a global variable
141 // if one exists in the DXE core for this Architectural Protocol
142 //
143 if (Entry->Protocol != NULL) {
144 *(Entry->Protocol) = Protocol;
145 }
146
147 //
148 // Do special operations for Architectural Protocols
149 //
150
151 if (CompareGuid (Entry->ProtocolGuid, &gEfiTimerArchProtocolGuid)) {
152 //
153 // Register the Core timer tick handler with the Timer AP
154 //
155 gTimer->RegisterHandler (gTimer, CoreTimerTick);
156 }
157
158 if (CompareGuid (Entry->ProtocolGuid, &gEfiRuntimeArchProtocolGuid)) {
159 //
160 // When runtime architectural protocol is available, updates CRC32 in the Debug Table
161 //
162 CoreUpdateDebugTableCrc32 ();
163
164 //
165 // Update the Runtime Architectural protocol with the template that the core was
166 // using so there would not need to be a dependency on the Runtime AP
167 //
168
169 //
170 // Copy all the registered Image to new gRuntime protocol
171 //
172 for (Link = gRuntimeTemplate.ImageHead.ForwardLink; Link != &gRuntimeTemplate.ImageHead; Link = TempLinkNode.ForwardLink) {
173 CopyMem (&TempLinkNode, Link, sizeof(LIST_ENTRY));
174 InsertTailList (&gRuntime->ImageHead, Link);
175 }
176 //
177 // Copy all the registered Event to new gRuntime protocol
178 //
179 for (Link = gRuntimeTemplate.EventHead.ForwardLink; Link != &gRuntimeTemplate.EventHead; Link = TempLinkNode.ForwardLink) {
180 CopyMem (&TempLinkNode, Link, sizeof(LIST_ENTRY));
181 InsertTailList (&gRuntime->EventHead, Link);
182 }
183
184 //
185 // Clean up gRuntimeTemplate
186 //
187 gRuntimeTemplate.ImageHead.ForwardLink = &gRuntimeTemplate.ImageHead;
188 gRuntimeTemplate.ImageHead.BackLink = &gRuntimeTemplate.ImageHead;
189 gRuntimeTemplate.EventHead.ForwardLink = &gRuntimeTemplate.EventHead;
190 gRuntimeTemplate.EventHead.BackLink = &gRuntimeTemplate.EventHead;
191 }
192
193 //
194 // It's over kill to do them all every time, but it saves a lot of code.
195 //
196 CalculateEfiHdrCrc (&gDxeCoreRT->Hdr);
197 CalculateEfiHdrCrc (&gBS->Hdr);
198 CalculateEfiHdrCrc (&gDxeCoreST->Hdr);
199 CalculateEfiHdrCrc (&gDxeCoreDS->Hdr);
200 }
201
202 /**
203 Creates an event for each entry in a table that is fired everytime a Protocol
204 of a specific type is installed.
205
206 @param Entry Pointer to EFI_CORE_PROTOCOL_NOTIFY_ENTRY.
207
208 **/
209 VOID
210 CoreNotifyOnProtocolEntryTable (
211 EFI_CORE_PROTOCOL_NOTIFY_ENTRY *Entry
212 )
213 {
214 EFI_STATUS Status;
215
216 for (; Entry->ProtocolGuid != NULL; Entry++) {
217 //
218 // Create the event
219 //
220 Status = CoreCreateEvent (
221 EVT_NOTIFY_SIGNAL,
222 TPL_CALLBACK,
223 GenericProtocolNotify,
224 Entry,
225 &Entry->Event
226 );
227 ASSERT_EFI_ERROR(Status);
228
229 //
230 // Register for protocol notifactions on this event
231 //
232 Status = CoreRegisterProtocolNotify (
233 Entry->ProtocolGuid,
234 Entry->Event,
235 &Entry->Registration
236 );
237 ASSERT_EFI_ERROR(Status);
238 }
239 }
240
241 /**
242 Creates an events for the Architectural Protocols and the optional protocols
243 that are fired everytime a Protocol of a specific type is installed.
244
245 **/
246 VOID
247 CoreNotifyOnProtocolInstallation (
248 VOID
249 )
250 {
251 CoreNotifyOnProtocolEntryTable (mArchProtocols);
252 CoreNotifyOnProtocolEntryTable (mOptionalProtocols);
253 }
254
255
256 /**
257 Displays Architectural protocols that were not loaded and are required for DXE
258 core to function. Only used in Debug Builds.
259
260 **/
261 VOID
262 CoreDisplayMissingArchProtocols (
263 VOID
264 )
265 {
266 EFI_CORE_PROTOCOL_NOTIFY_ENTRY *Entry;
267 CONST GUID_TO_STRING_PROTOCOL_ENTRY *MissingEntry;
268
269 for (Entry = mArchProtocols; Entry->ProtocolGuid != NULL; Entry++) {
270 if (!Entry->Present) {
271 for (MissingEntry = mMissingProtocols; MissingEntry->ProtocolGuid != NULL; MissingEntry++) {
272 if (CompareGuid (Entry->ProtocolGuid, MissingEntry->ProtocolGuid)) {
273 DEBUG ((DEBUG_ERROR, "\n%a Arch Protocol not present!!\n", MissingEntry->GuidString));
274 break;
275 }
276 }
277 }
278 }
279 }