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