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