]> git.proxmox.com Git - mirror_edk2.git/blob - IntelFrameworkModulePkg/Universal/StatusCode/RuntimeDxe/StatusCodeRuntimeDxe.c
03dc4cb45d73b69351ee72eb8d519aad3790b875
[mirror_edk2.git] / IntelFrameworkModulePkg / Universal / StatusCode / RuntimeDxe / StatusCodeRuntimeDxe.c
1 /** @file
2 Status code driver for IA32/X64/EBC architecture.
3
4 Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
6
7 **/
8
9 #include "StatusCodeRuntimeDxe.h"
10
11 EFI_EVENT mVirtualAddressChangeEvent = NULL;
12 EFI_HANDLE mHandle = NULL;
13
14 //
15 // Declaration of status code protocol.
16 //
17 EFI_STATUS_CODE_PROTOCOL mEfiStatusCodeProtocol = {
18 ReportDispatcher
19 };
20
21 //
22 // Report operation nest status.
23 // If it is set, then the report operation has nested.
24 //
25 UINT32 mStatusCodeNestStatus = 0;
26
27 /**
28 Entry point of DXE Status Code Driver.
29
30 This function is the entry point of this DXE Status Code Driver.
31 It installs Status Code Runtime Protocol, and registers event for EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE.
32
33 @param ImageHandle The firmware allocated handle for the EFI image.
34 @param SystemTable A pointer to the EFI System Table.
35
36 @retval EFI_SUCCESS The entry point is executed successfully.
37
38 **/
39 EFI_STATUS
40 EFIAPI
41 StatusCodeRuntimeDxeEntry (
42 IN EFI_HANDLE ImageHandle,
43 IN EFI_SYSTEM_TABLE *SystemTable
44 )
45 {
46 EFI_STATUS Status;
47
48 //
49 // Dispatch initialization request to supported devices
50 //
51 InitializationDispatcherWorker ();
52
53 //
54 // Install Status Code Runtime Protocol implementation as defined in PI Specification.
55 //
56 Status = gBS->InstallMultipleProtocolInterfaces (
57 &mHandle,
58 &gEfiStatusCodeRuntimeProtocolGuid,
59 &mEfiStatusCodeProtocol,
60 NULL
61 );
62 ASSERT_EFI_ERROR (Status);
63
64 Status = gBS->CreateEventEx (
65 EVT_NOTIFY_SIGNAL,
66 TPL_NOTIFY,
67 VirtualAddressChangeCallBack,
68 NULL,
69 &gEfiEventVirtualAddressChangeGuid,
70 &mVirtualAddressChangeEvent
71 );
72 ASSERT_EFI_ERROR (Status);
73
74 return EFI_SUCCESS;
75 }
76
77 /**
78 Report status code to all supported device.
79
80 This function implements EFI_STATUS_CODE_PROTOCOL.ReportStatusCode().
81 It calls into the workers which dispatches the platform specific listeners.
82
83 @param CodeType Indicates the type of status code being reported.
84 @param Value Describes the current status of a hardware or software entity.
85 This included information about the class and subclass that is used to
86 classify the entity as well as an operation.
87 @param Instance The enumeration of a hardware or software entity within
88 the system. Valid instance numbers start with 1.
89 @param CallerId This optional parameter may be used to identify the caller.
90 This parameter allows the status code driver to apply different rules to
91 different callers.
92 @param Data This optional parameter may be used to pass additional data.
93
94 @retval EFI_SUCCESS The function completed successfully
95 @retval EFI_DEVICE_ERROR The function should not be completed due to a device error.
96
97 **/
98 EFI_STATUS
99 EFIAPI
100 ReportDispatcher (
101 IN EFI_STATUS_CODE_TYPE CodeType,
102 IN EFI_STATUS_CODE_VALUE Value,
103 IN UINT32 Instance,
104 IN EFI_GUID *CallerId OPTIONAL,
105 IN EFI_STATUS_CODE_DATA *Data OPTIONAL
106 )
107 {
108 //
109 // Use atom operation to avoid the reentant of report.
110 // If current status is not zero, then the function is reentrancy.
111 //
112 if (InterlockedCompareExchange32 (&mStatusCodeNestStatus, 0, 1) == 1) {
113 return EFI_DEVICE_ERROR;
114 }
115
116 if (FeaturePcdGet (PcdStatusCodeUseSerial)) {
117 SerialStatusCodeReportWorker (
118 CodeType,
119 Value,
120 Instance,
121 CallerId,
122 Data
123 );
124 }
125 if (FeaturePcdGet (PcdStatusCodeUseMemory)) {
126 RtMemoryStatusCodeReportWorker (
127 CodeType,
128 Value,
129 Instance
130 );
131 }
132 if (FeaturePcdGet (PcdStatusCodeUseDataHub)) {
133 DataHubStatusCodeReportWorker (
134 CodeType,
135 Value,
136 Instance,
137 CallerId,
138 Data
139 );
140 }
141 if (FeaturePcdGet (PcdStatusCodeUseOEM)) {
142 //
143 // Call OEM hook status code library API to report status code to OEM device
144 //
145 OemHookStatusCodeReport (
146 CodeType,
147 Value,
148 Instance,
149 CallerId,
150 Data
151 );
152 }
153
154 //
155 // Restore the nest status of report
156 //
157 InterlockedCompareExchange32 (&mStatusCodeNestStatus, 1, 0);
158
159 return EFI_SUCCESS;
160 }
161
162
163 /**
164 Virtual address change notification call back. It converts global pointer
165 to virtual address.
166
167 @param Event Event whose notification function is being invoked.
168 @param Context Pointer to the notification function's context, which is
169 always zero in current implementation.
170
171 **/
172 VOID
173 EFIAPI
174 VirtualAddressChangeCallBack (
175 IN EFI_EVENT Event,
176 IN VOID *Context
177 )
178 {
179 //
180 // Convert memory status code table to virtual address;
181 //
182 EfiConvertPointer (
183 0,
184 (VOID **) &mRtMemoryStatusCodeTable
185 );
186 }
187
188 /**
189 Dispatch initialization request to sub status code devices based on
190 customized feature flags.
191
192 **/
193 VOID
194 InitializationDispatcherWorker (
195 VOID
196 )
197 {
198 EFI_PEI_HOB_POINTERS Hob;
199 EFI_STATUS Status;
200 MEMORY_STATUSCODE_PACKET_HEADER *PacketHeader;
201 MEMORY_STATUSCODE_RECORD *Record;
202 UINTN Index;
203 UINTN MaxRecordNumber;
204
205 //
206 // If enable UseSerial, then initialize serial port.
207 // if enable UseRuntimeMemory, then initialize runtime memory status code worker.
208 // if enable UseDataHub, then initialize data hub status code worker.
209 //
210 if (FeaturePcdGet (PcdStatusCodeUseSerial)) {
211 //
212 // Call Serial Port Lib API to initialize serial port.
213 //
214 Status = SerialPortInitialize ();
215 ASSERT_EFI_ERROR (Status);
216 }
217 if (FeaturePcdGet (PcdStatusCodeUseMemory)) {
218 Status = RtMemoryStatusCodeInitializeWorker ();
219 ASSERT_EFI_ERROR (Status);
220 }
221 if (FeaturePcdGet (PcdStatusCodeUseDataHub)) {
222 DataHubStatusCodeInitializeWorker ();
223 }
224 if (FeaturePcdGet (PcdStatusCodeUseOEM)) {
225 //
226 // Call OEM hook status code library API to initialize OEM device for status code.
227 //
228 Status = OemHookStatusCodeInitialize ();
229 ASSERT_EFI_ERROR (Status);
230 }
231
232 //
233 // Replay Status code which saved in GUID'ed HOB to all supported devices.
234 //
235 if (FeaturePcdGet (PcdStatusCodeReplayIn)) {
236 //
237 // Journal GUID'ed HOBs to find all record entry, if found,
238 // then output record to support replay device.
239 //
240 Hob.Raw = GetFirstGuidHob (&gMemoryStatusCodeRecordGuid);
241 if (Hob.Raw != NULL) {
242 PacketHeader = (MEMORY_STATUSCODE_PACKET_HEADER *) GET_GUID_HOB_DATA (Hob.Guid);
243 Record = (MEMORY_STATUSCODE_RECORD *) (PacketHeader + 1);
244 MaxRecordNumber = (UINTN) PacketHeader->RecordIndex;
245 if (PacketHeader->PacketIndex > 0) {
246 //
247 // Record has been wrapped around. So, record number has arrived at max number.
248 //
249 MaxRecordNumber = (UINTN) PacketHeader->MaxRecordsNumber;
250 }
251 for (Index = 0; Index < MaxRecordNumber; Index++) {
252 //
253 // Dispatch records to devices based on feature flag.
254 //
255 if (FeaturePcdGet (PcdStatusCodeUseSerial)) {
256 SerialStatusCodeReportWorker (
257 Record[Index].CodeType,
258 Record[Index].Value,
259 Record[Index].Instance,
260 NULL,
261 NULL
262 );
263 }
264 if (FeaturePcdGet (PcdStatusCodeUseMemory)) {
265 RtMemoryStatusCodeReportWorker (
266 Record[Index].CodeType,
267 Record[Index].Value,
268 Record[Index].Instance
269 );
270 }
271 if (FeaturePcdGet (PcdStatusCodeUseDataHub)) {
272 DataHubStatusCodeReportWorker (
273 Record[Index].CodeType,
274 Record[Index].Value,
275 Record[Index].Instance,
276 NULL,
277 NULL
278 );
279 }
280 if (FeaturePcdGet (PcdStatusCodeUseOEM)) {
281 //
282 // Call OEM hook status code library API to report status code to OEM device
283 //
284 OemHookStatusCodeReport (
285 Record[Index].CodeType,
286 Record[Index].Value,
287 Record[Index].Instance,
288 NULL,
289 NULL
290 );
291 }
292 }
293 }
294 }
295 }