]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Core/Dxe/DxeMain/DxeProtocolNotify.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[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
92 return EFI_SUCCESS;
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 //
178 // Copy all the registered Event to new gRuntime protocol
179 //
180 for (Link = gRuntimeTemplate.EventHead.ForwardLink; Link != &gRuntimeTemplate.EventHead; Link = TempLinkNode.ForwardLink) {
181 CopyMem (&TempLinkNode, Link, sizeof (LIST_ENTRY));
182 InsertTailList (&gRuntime->EventHead, Link);
183 }
184
185 //
186 // Clean up gRuntimeTemplate
187 //
188 gRuntimeTemplate.ImageHead.ForwardLink = &gRuntimeTemplate.ImageHead;
189 gRuntimeTemplate.ImageHead.BackLink = &gRuntimeTemplate.ImageHead;
190 gRuntimeTemplate.EventHead.ForwardLink = &gRuntimeTemplate.EventHead;
191 gRuntimeTemplate.EventHead.BackLink = &gRuntimeTemplate.EventHead;
192 }
193
194 //
195 // It's over kill to do them all every time, but it saves a lot of code.
196 //
197 CalculateEfiHdrCrc (&gDxeCoreRT->Hdr);
198 CalculateEfiHdrCrc (&gBS->Hdr);
199 CalculateEfiHdrCrc (&gDxeCoreST->Hdr);
200 CalculateEfiHdrCrc (&gDxeCoreDS->Hdr);
201 }
202
203 /**
204 Creates an event for each entry in a table that is fired everytime a Protocol
205 of a specific type is installed.
206
207 @param Entry Pointer to EFI_CORE_PROTOCOL_NOTIFY_ENTRY.
208
209 **/
210 VOID
211 CoreNotifyOnProtocolEntryTable (
212 EFI_CORE_PROTOCOL_NOTIFY_ENTRY *Entry
213 )
214 {
215 EFI_STATUS Status;
216
217 for ( ; Entry->ProtocolGuid != NULL; Entry++) {
218 //
219 // Create the event
220 //
221 Status = CoreCreateEvent (
222 EVT_NOTIFY_SIGNAL,
223 TPL_CALLBACK,
224 GenericProtocolNotify,
225 Entry,
226 &Entry->Event
227 );
228 ASSERT_EFI_ERROR (Status);
229
230 //
231 // Register for protocol notifactions on this event
232 //
233 Status = CoreRegisterProtocolNotify (
234 Entry->ProtocolGuid,
235 Entry->Event,
236 &Entry->Registration
237 );
238 ASSERT_EFI_ERROR (Status);
239 }
240 }
241
242 /**
243 Creates an events for the Architectural Protocols and the optional protocols
244 that are fired everytime a Protocol of a specific type is installed.
245
246 **/
247 VOID
248 CoreNotifyOnProtocolInstallation (
249 VOID
250 )
251 {
252 CoreNotifyOnProtocolEntryTable (mArchProtocols);
253 CoreNotifyOnProtocolEntryTable (mOptionalProtocols);
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 }