]> git.proxmox.com Git - mirror_edk2.git/blob - EdkModulePkg/Core/Dxe/DxeMain/DxeProtocolNotify.c
51bc23ad3d422c3e046671f5ed11d64a331a9f9a
[mirror_edk2.git] / EdkModulePkg / Core / Dxe / DxeMain / DxeProtocolNotify.c
1 /*++
2
3 Copyright (c) 2006 - 2007, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
8
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
11
12 Module Name:
13
14 DxeProtocolNotify.c
15
16 Abstract:
17
18 This file deals with Architecture Protocol (AP) registration in
19 the Dxe Core. The mArchProtocols[] array represents a list of
20 events that represent the Architectural Protocols.
21
22 --*/
23
24 #include <DxeMain.h>
25
26
27 //
28 // DXE Core Global Variables for all of the Architectural Protocols.
29 // If a protocol is installed mArchProtocols[].Present will be TRUE.
30 //
31 // CoreNotifyOnArchProtocolInstallation () fills in mArchProtocols[].Event
32 // and mArchProtocols[].Registration as it creates events for every array
33 // entry.
34 //
35
36 ARCHITECTURAL_PROTOCOL_ENTRY mArchProtocols[] = {
37 { &gEfiSecurityArchProtocolGuid, (VOID **)&gSecurity, NULL, NULL, FALSE },
38 { &gEfiCpuArchProtocolGuid, (VOID **)&gCpu, NULL, NULL, FALSE },
39 { &gEfiMetronomeArchProtocolGuid, (VOID **)&gMetronome, NULL, NULL, FALSE },
40 { &gEfiTimerArchProtocolGuid, (VOID **)&gTimer, NULL, NULL, FALSE },
41 { &gEfiBdsArchProtocolGuid, (VOID **)&gBds, NULL, NULL, FALSE },
42 { &gEfiWatchdogTimerArchProtocolGuid, (VOID **)&gWatchdogTimer, NULL, NULL, FALSE },
43 { &gEfiRuntimeArchProtocolGuid, (VOID **)&gRuntime, NULL, NULL, FALSE },
44 { &gEfiVariableArchProtocolGuid, (VOID **)NULL, NULL, NULL, FALSE },
45 { &gEfiVariableWriteArchProtocolGuid, (VOID **)NULL, NULL, NULL, FALSE },
46 #ifndef MDE_CPU_IPF
47 //
48 // UEFI 2.0 added support for Capsule services. DXE CIS ??? Added support for this AP
49 //
50 { &gEfiCapsuleArchProtocolGuid, (VOID **)NULL, NULL, NULL, FALSE},
51 #endif
52 { &gEfiMonotonicCounterArchProtocolGuid, (VOID **)NULL, NULL, NULL, FALSE },
53 { &gEfiResetArchProtocolGuid, (VOID **)NULL, NULL, NULL, FALSE },
54 { &gEfiRealTimeClockArchProtocolGuid, (VOID **)NULL, NULL, NULL, FALSE },
55 { NULL, (VOID **)NULL, NULL, NULL, FALSE }
56 };
57
58
59 EFI_STATUS
60 CoreAllEfiServicesAvailable (
61 VOID
62 )
63 /*++
64
65 Routine Description:
66 Return TRUE if all AP services are availible.
67
68 Arguments:
69 NONE
70
71 Returns:
72 EFI_SUCCESS - All AP services are available
73 EFI_NOT_FOUND - At least one AP service is not available
74
75 --*/
76 {
77 ARCHITECTURAL_PROTOCOL_ENTRY *Entry;
78
79 for (Entry = mArchProtocols; Entry->ProtocolGuid != NULL; Entry++) {
80 if (!Entry->Present) {
81 return EFI_NOT_FOUND;
82 }
83 }
84
85 return EFI_SUCCESS;
86 }
87
88 STATIC
89 VOID
90 EFIAPI
91 GenericArchProtocolNotify (
92 IN EFI_EVENT Event,
93 IN VOID *Context
94 )
95 /*++
96
97 Routine Description:
98 Notification event handler registered by CoreNotifyOnArchProtocolInstallation ().
99 This notify function is registered for every architectural protocol. This handler
100 updates mArchProtocol[] array entry with protocol instance data and sets it's
101 present flag to TRUE. If any constructor is required it is executed. The EFI
102 System Table headers are updated.
103
104 Arguments:
105
106 Event - The Event that is being processed, not used.
107
108 Context - Event Context, not used.
109
110 Returns:
111
112 None
113
114 --*/
115 {
116 EFI_STATUS Status;
117 ARCHITECTURAL_PROTOCOL_ENTRY *Entry;
118 VOID *Protocol;
119 BOOLEAN Found;
120 LIST_ENTRY *Link;
121 LIST_ENTRY TempLinkNode;
122
123 Found = FALSE;
124 for (Entry = mArchProtocols; Entry->ProtocolGuid != NULL; Entry++) {
125
126 Status = CoreLocateProtocol (Entry->ProtocolGuid, Entry->Registration, &Protocol);
127 if (EFI_ERROR (Status)) {
128 continue;
129 }
130
131 Found = TRUE;
132 Entry->Present = TRUE;
133
134 //
135 // Update protocol global variable if one exists. Entry->Protocol points to a global variable
136 // if one exists in the DXE core for this Architectural Protocol
137 //
138 if (Entry->Protocol != NULL) {
139 *(Entry->Protocol) = Protocol;
140 }
141
142 if (CompareGuid (Entry->ProtocolGuid, &gEfiTimerArchProtocolGuid)) {
143 //
144 // Register the Core timer tick handler with the Timer AP
145 //
146 gTimer->RegisterHandler (gTimer, CoreTimerTick);
147 }
148
149 if (CompareGuid (Entry->ProtocolGuid, &gEfiRuntimeArchProtocolGuid)) {
150 //
151 // When runtime architectural protocol is available, updates CRC32 in the Debug Table
152 //
153 CoreUpdateDebugTableCrc32 ();
154
155 //
156 // Update the Runtime Architectural protocol with the template that the core was
157 // using so there would not need to be a dependency on the Runtime AP
158 //
159
160 //
161 // Copy all the registered Image to new gRuntime protocol
162 //
163 for (Link = gRuntimeTemplate.ImageHead.ForwardLink; Link != &gRuntimeTemplate.ImageHead; Link = TempLinkNode.ForwardLink) {
164 CopyMem (&TempLinkNode, Link, sizeof(LIST_ENTRY));
165 InsertTailList (&gRuntime->ImageHead, Link);
166 }
167 //
168 // Copy all the registered Event to new gRuntime protocol
169 //
170 for (Link = gRuntimeTemplate.EventHead.ForwardLink; Link != &gRuntimeTemplate.EventHead; Link = TempLinkNode.ForwardLink) {
171 CopyMem (&TempLinkNode, Link, sizeof(LIST_ENTRY));
172 InsertTailList (&gRuntime->EventHead, Link);
173 }
174
175 //
176 // Clean up gRuntimeTemplate
177 //
178 gRuntimeTemplate.ImageHead.ForwardLink = &gRuntimeTemplate.ImageHead;
179 gRuntimeTemplate.ImageHead.BackLink = &gRuntimeTemplate.ImageHead;
180 gRuntimeTemplate.EventHead.ForwardLink = &gRuntimeTemplate.EventHead;
181 gRuntimeTemplate.EventHead.BackLink = &gRuntimeTemplate.EventHead;
182 }
183 }
184
185 //
186 // It's over kill to do them all every time, but it saves a lot of code.
187 //
188 if (Found) {
189 CalculateEfiHdrCrc (&gRT->Hdr);
190 CalculateEfiHdrCrc (&gBS->Hdr);
191 CalculateEfiHdrCrc (&gST->Hdr);
192 CalculateEfiHdrCrc (&gDS->Hdr);
193 }
194 }
195
196
197
198 VOID
199 CoreNotifyOnArchProtocolInstallation (
200 VOID
201 )
202 /*++
203
204 Routine Description:
205 Creates an event that is fired everytime a Protocol of a specific type is installed
206
207 Arguments:
208 NONE
209
210 Returns:
211 NONE
212
213 --*/
214 {
215 EFI_STATUS Status;
216 ARCHITECTURAL_PROTOCOL_ENTRY *Entry;
217
218 for (Entry = mArchProtocols; Entry->ProtocolGuid != NULL; Entry++) {
219
220 //
221 // Create the event
222 //
223 Status = CoreCreateEvent (
224 EFI_EVENT_NOTIFY_SIGNAL,
225 EFI_TPL_CALLBACK,
226 GenericArchProtocolNotify,
227 NULL,
228 &Entry->Event
229 );
230 ASSERT_EFI_ERROR(Status);
231
232 //
233 // Register for protocol notifactions on this event
234 //
235 Status = CoreRegisterProtocolNotify (
236 Entry->ProtocolGuid,
237 Entry->Event,
238 &Entry->Registration
239 );
240 ASSERT_EFI_ERROR(Status);
241
242 }
243 }
244
245 //
246 // Following is needed to display missing architectural protocols in debug builds
247 //
248 typedef struct {
249 EFI_GUID *ProtocolGuid;
250 CHAR16 *GuidString;
251 } GUID_TO_STRING_PROTOCOL_ENTRY;
252
253 static const GUID_TO_STRING_PROTOCOL_ENTRY MissingProtocols[] = {
254 { &gEfiSecurityArchProtocolGuid, (CHAR16 *)L"Security" },
255 { &gEfiCpuArchProtocolGuid, (CHAR16 *)L"CPU" },
256 { &gEfiMetronomeArchProtocolGuid, (CHAR16 *)L"Metronome" },
257 { &gEfiTimerArchProtocolGuid, (CHAR16 *)L"Timer" },
258 { &gEfiBdsArchProtocolGuid, (CHAR16 *)L"Bds" },
259 { &gEfiWatchdogTimerArchProtocolGuid, (CHAR16 *)L"Watchdog Timer" },
260 { &gEfiRuntimeArchProtocolGuid, (CHAR16 *)L"Runtime" },
261 { &gEfiVariableArchProtocolGuid, (CHAR16 *)L"Variable" },
262 { &gEfiVariableWriteArchProtocolGuid, (CHAR16 *)L"Variable Write" },
263 { &gEfiCapsuleArchProtocolGuid, (CHAR16 *)L"Capsule" },
264 { &gEfiMonotonicCounterArchProtocolGuid, (CHAR16 *)L"Monotonic Counter" },
265 { &gEfiResetArchProtocolGuid, (CHAR16 *)L"Reset" },
266 // { &gEfiStatusCodeRuntimeProtocolGuid, (CHAR16 *)L"Status Code" },
267 { &gEfiRealTimeClockArchProtocolGuid, (CHAR16 *)L"Real Time Clock" }
268 };
269
270 VOID
271 CoreDisplayMissingArchProtocols (
272 VOID
273 )
274 /*++
275
276 Routine Description:
277 Displays Architectural protocols that were not loaded and are required for DXE core to function
278 Only used in Debug Builds
279
280 Arguments:
281 NONE
282
283 Returns:
284 NONE
285
286 --*/
287 {
288 const GUID_TO_STRING_PROTOCOL_ENTRY *MissingEntry;
289 ARCHITECTURAL_PROTOCOL_ENTRY *Entry;
290
291 for (Entry = mArchProtocols; Entry->ProtocolGuid != NULL; Entry++) {
292 if (!Entry->Present) {
293 MissingEntry = MissingProtocols;
294 for (MissingEntry = MissingProtocols; TRUE ; MissingEntry++) {
295 if (CompareGuid (Entry->ProtocolGuid, MissingEntry->ProtocolGuid)) {
296 DEBUG ((EFI_D_ERROR, "\n%s Arch Protocol not present!!\n", MissingEntry->GuidString));
297 break;
298 }
299 }
300 }
301 }
302 }