1) Initialize gBS, gST, gImageHandle in UefiBootServicesTableLib.c to NULL
[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 { &gEfiCapsuleArchProtocolGuid, (VOID **)NULL, NULL, NULL, FALSE},
47 { &gEfiMonotonicCounterArchProtocolGuid, (VOID **)NULL, NULL, NULL, FALSE },
48 { &gEfiResetArchProtocolGuid, (VOID **)NULL, NULL, NULL, FALSE },
49 { &gEfiRealTimeClockArchProtocolGuid, (VOID **)NULL, NULL, NULL, FALSE },
50 { NULL, (VOID **)NULL, NULL, NULL, FALSE }
51 };
52
53
54 EFI_STATUS
55 CoreAllEfiServicesAvailable (
56 VOID
57 )
58 /*++
59
60 Routine Description:
61 Return TRUE if all AP services are availible.
62
63 Arguments:
64 NONE
65
66 Returns:
67 EFI_SUCCESS - All AP services are available
68 EFI_NOT_FOUND - At least one AP service is not available
69
70 --*/
71 {
72 ARCHITECTURAL_PROTOCOL_ENTRY *Entry;
73
74 for (Entry = mArchProtocols; Entry->ProtocolGuid != NULL; Entry++) {
75 if (!Entry->Present) {
76 return EFI_NOT_FOUND;
77 }
78 }
79
80 return EFI_SUCCESS;
81 }
82
83 STATIC
84 VOID
85 EFIAPI
86 GenericArchProtocolNotify (
87 IN EFI_EVENT Event,
88 IN VOID *Context
89 )
90 /*++
91
92 Routine Description:
93 Notification event handler registered by CoreNotifyOnArchProtocolInstallation ().
94 This notify function is registered for every architectural protocol. This handler
95 updates mArchProtocol[] array entry with protocol instance data and sets it's
96 present flag to TRUE. If any constructor is required it is executed. The EFI
97 System Table headers are updated.
98
99 Arguments:
100
101 Event - The Event that is being processed, not used.
102
103 Context - Event Context, not used.
104
105 Returns:
106
107 None
108
109 --*/
110 {
111 EFI_STATUS Status;
112 ARCHITECTURAL_PROTOCOL_ENTRY *Entry;
113 VOID *Protocol;
114 BOOLEAN Found;
115 LIST_ENTRY *Link;
116 LIST_ENTRY TempLinkNode;
117
118 Found = FALSE;
119 for (Entry = mArchProtocols; Entry->ProtocolGuid != NULL; Entry++) {
120
121 Status = CoreLocateProtocol (Entry->ProtocolGuid, Entry->Registration, &Protocol);
122 if (EFI_ERROR (Status)) {
123 continue;
124 }
125
126 Found = TRUE;
127 Entry->Present = TRUE;
128
129 //
130 // Update protocol global variable if one exists. Entry->Protocol points to a global variable
131 // if one exists in the DXE core for this Architectural Protocol
132 //
133 if (Entry->Protocol != NULL) {
134 *(Entry->Protocol) = Protocol;
135 }
136
137 if (CompareGuid (Entry->ProtocolGuid, &gEfiTimerArchProtocolGuid)) {
138 //
139 // Register the Core timer tick handler with the Timer AP
140 //
141 gTimer->RegisterHandler (gTimer, CoreTimerTick);
142 }
143
144 if (CompareGuid (Entry->ProtocolGuid, &gEfiRuntimeArchProtocolGuid)) {
145 //
146 // When runtime architectural protocol is available, updates CRC32 in the Debug Table
147 //
148 CoreUpdateDebugTableCrc32 ();
149
150 //
151 // Update the Runtime Architectural protocol with the template that the core was
152 // using so there would not need to be a dependency on the Runtime AP
153 //
154
155 //
156 // Copy all the registered Image to new gRuntime protocol
157 //
158 for (Link = gRuntimeTemplate.ImageHead.ForwardLink; Link != &gRuntimeTemplate.ImageHead; Link = TempLinkNode.ForwardLink) {
159 CopyMem (&TempLinkNode, Link, sizeof(LIST_ENTRY));
160 InsertTailList (&gRuntime->ImageHead, Link);
161 }
162 //
163 // Copy all the registered Event to new gRuntime protocol
164 //
165 for (Link = gRuntimeTemplate.EventHead.ForwardLink; Link != &gRuntimeTemplate.EventHead; Link = TempLinkNode.ForwardLink) {
166 CopyMem (&TempLinkNode, Link, sizeof(LIST_ENTRY));
167 InsertTailList (&gRuntime->EventHead, Link);
168 }
169
170 //
171 // Clean up gRuntimeTemplate
172 //
173 gRuntimeTemplate.ImageHead.ForwardLink = &gRuntimeTemplate.ImageHead;
174 gRuntimeTemplate.ImageHead.BackLink = &gRuntimeTemplate.ImageHead;
175 gRuntimeTemplate.EventHead.ForwardLink = &gRuntimeTemplate.EventHead;
176 gRuntimeTemplate.EventHead.BackLink = &gRuntimeTemplate.EventHead;
177 }
178 }
179
180 //
181 // It's over kill to do them all every time, but it saves a lot of code.
182 //
183 if (Found) {
184 CalculateEfiHdrCrc (&gDxeCoreRT->Hdr);
185 CalculateEfiHdrCrc (&gDxeCoreBS->Hdr);
186 CalculateEfiHdrCrc (&gDxeCoreST->Hdr);
187 CalculateEfiHdrCrc (&gDxeCoreDS->Hdr);
188 }
189 }
190
191
192
193 VOID
194 CoreNotifyOnArchProtocolInstallation (
195 VOID
196 )
197 /*++
198
199 Routine Description:
200 Creates an event that is fired everytime a Protocol of a specific type is installed
201
202 Arguments:
203 NONE
204
205 Returns:
206 NONE
207
208 --*/
209 {
210 EFI_STATUS Status;
211 ARCHITECTURAL_PROTOCOL_ENTRY *Entry;
212
213 for (Entry = mArchProtocols; Entry->ProtocolGuid != NULL; Entry++) {
214
215 //
216 // Create the event
217 //
218 Status = CoreCreateEvent (
219 EFI_EVENT_NOTIFY_SIGNAL,
220 EFI_TPL_CALLBACK,
221 GenericArchProtocolNotify,
222 NULL,
223 &Entry->Event
224 );
225 ASSERT_EFI_ERROR(Status);
226
227 //
228 // Register for protocol notifactions on this event
229 //
230 Status = CoreRegisterProtocolNotify (
231 Entry->ProtocolGuid,
232 Entry->Event,
233 &Entry->Registration
234 );
235 ASSERT_EFI_ERROR(Status);
236
237 }
238 }
239
240 //
241 // Following is needed to display missing architectural protocols in debug builds
242 //
243 typedef struct {
244 EFI_GUID *ProtocolGuid;
245 CHAR16 *GuidString;
246 } GUID_TO_STRING_PROTOCOL_ENTRY;
247
248 static const GUID_TO_STRING_PROTOCOL_ENTRY MissingProtocols[] = {
249 { &gEfiSecurityArchProtocolGuid, (CHAR16 *)L"Security" },
250 { &gEfiCpuArchProtocolGuid, (CHAR16 *)L"CPU" },
251 { &gEfiMetronomeArchProtocolGuid, (CHAR16 *)L"Metronome" },
252 { &gEfiTimerArchProtocolGuid, (CHAR16 *)L"Timer" },
253 { &gEfiBdsArchProtocolGuid, (CHAR16 *)L"Bds" },
254 { &gEfiWatchdogTimerArchProtocolGuid, (CHAR16 *)L"Watchdog Timer" },
255 { &gEfiRuntimeArchProtocolGuid, (CHAR16 *)L"Runtime" },
256 { &gEfiVariableArchProtocolGuid, (CHAR16 *)L"Variable" },
257 { &gEfiVariableWriteArchProtocolGuid, (CHAR16 *)L"Variable Write" },
258 { &gEfiCapsuleArchProtocolGuid, (CHAR16 *)L"Capsule" },
259 { &gEfiMonotonicCounterArchProtocolGuid, (CHAR16 *)L"Monotonic Counter" },
260 { &gEfiResetArchProtocolGuid, (CHAR16 *)L"Reset" },
261 // { &gEfiStatusCodeRuntimeProtocolGuid, (CHAR16 *)L"Status Code" },
262 { &gEfiRealTimeClockArchProtocolGuid, (CHAR16 *)L"Real Time Clock" }
263 };
264
265 VOID
266 CoreDisplayMissingArchProtocols (
267 VOID
268 )
269 /*++
270
271 Routine Description:
272 Displays Architectural protocols that were not loaded and are required for DXE core to function
273 Only used in Debug Builds
274
275 Arguments:
276 NONE
277
278 Returns:
279 NONE
280
281 --*/
282 {
283 const GUID_TO_STRING_PROTOCOL_ENTRY *MissingEntry;
284 ARCHITECTURAL_PROTOCOL_ENTRY *Entry;
285
286 for (Entry = mArchProtocols; Entry->ProtocolGuid != NULL; Entry++) {
287 if (!Entry->Present) {
288 MissingEntry = MissingProtocols;
289 for (MissingEntry = MissingProtocols; TRUE ; MissingEntry++) {
290 if (CompareGuid (Entry->ProtocolGuid, MissingEntry->ProtocolGuid)) {
291 DEBUG ((EFI_D_ERROR, "\n%s Arch Protocol not present!!\n", MissingEntry->GuidString));
292 break;
293 }
294 }
295 }
296 }
297 }