]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Library/DxeDebugPrintErrorLevelLib/DxeDebugPrintErrorLevelLib.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / MdeModulePkg / Library / DxeDebugPrintErrorLevelLib / DxeDebugPrintErrorLevelLib.c
1 /** @file
2 Debug Print Error Level library instance that provide compatibility with the
3 "err" shell command. This includes support for the Debug Mask Protocol
4 supports for global debug print error level mask stored in an EFI Variable.
5 This library instance only support DXE Phase modules.
6
7 Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR>
8 SPDX-License-Identifier: BSD-2-Clause-Patent
9
10 **/
11
12 #include <PiDxe.h>
13
14 #include <Library/DebugPrintErrorLevelLib.h>
15 #include <Library/PcdLib.h>
16 #include <Library/HobLib.h>
17
18 #include <Guid/DebugMask.h>
19
20 ///
21 /// Debug Mask Protocol function prototypes
22 ///
23
24 /**
25 Retrieves the current debug print error level mask for a module are returns
26 it in CurrentDebugMask.
27
28 @param This The protocol instance pointer.
29 @param CurrentDebugMask Pointer to the debug print error level mask that
30 is returned.
31
32 @retval EFI_SUCCESS The current debug print error level mask was
33 returned in CurrentDebugMask.
34 @retval EFI_INVALID_PARAMETER CurrentDebugMask is NULL.
35 @retval EFI_DEVICE_ERROR The current debug print error level mask could
36 not be retrieved.
37
38 **/
39 EFI_STATUS
40 EFIAPI
41 GetDebugMask (
42 IN EFI_DEBUG_MASK_PROTOCOL *This,
43 IN OUT UINTN *CurrentDebugMask
44 );
45
46 /**
47 Sets the current debug print error level mask for a module to the value
48 specified by NewDebugMask.
49
50 @param This The protocol instance pointer.
51 @param NewDebugMask The new debug print error level mask for this module.
52
53 @retval EFI_SUCCESS The current debug print error level mask was
54 set to the value specified by NewDebugMask.
55 @retval EFI_DEVICE_ERROR The current debug print error level mask could
56 not be set to the value specified by NewDebugMask.
57
58 **/
59 EFI_STATUS
60 EFIAPI
61 SetDebugMask (
62 IN EFI_DEBUG_MASK_PROTOCOL *This,
63 IN UINTN NewDebugMask
64 );
65
66 ///
67 /// Debug Mask Protocol instance
68 ///
69 EFI_DEBUG_MASK_PROTOCOL mDebugMaskProtocol = {
70 EFI_DEBUG_MASK_REVISION,
71 GetDebugMask,
72 SetDebugMask
73 };
74
75 ///
76 /// Global variable that is set to TRUE after the first attempt is made to
77 /// retrieve the global error level mask through the EFI Varibale Services.
78 /// This variable prevents the EFI Variable Services from being called fort
79 /// every DEBUG() macro.
80 ///
81 BOOLEAN mGlobalErrorLevelInitialized = FALSE;
82
83 ///
84 /// Global variable that contains the current debug error level mask for the
85 /// module that is using this library instance. This variable is initially
86 /// set to the PcdDebugPrintErrorLevel value. If the EFI Variable exists that
87 /// contains the global debug print error level mask, then that overrides the
88 /// PcdDebugPrintErrorLevel value. The EFI Variable can optionally be
89 /// discovered via a HOB so early DXE drivers can access the variable. If the
90 /// Debug Mask Protocol SetDebugMask() service is called, then that overrides
91 /// the PcdDebugPrintErrorLevel and the EFI Variable setting.
92 ///
93 UINT32 mDebugPrintErrorLevel = 0;
94
95 ///
96 /// Global variable that is used to cache a pointer to the EFI System Table
97 /// that is required to access the EFI Variable Services to get and set
98 /// the global debug print error level mask value. The UefiBootServicesTableLib
99 /// is not used to prevent a circular dependency between these libraries.
100 ///
101 EFI_SYSTEM_TABLE *mSystemTable = NULL;
102
103 /**
104 The constructor function caches the PCI Express Base Address and creates a
105 Set Virtual Address Map event to convert physical address to virtual addresses.
106
107 @param ImageHandle The firmware allocated handle for the EFI image.
108 @param SystemTable A pointer to the EFI System Table.
109
110 @retval EFI_SUCCESS The constructor completed successfully.
111 @retval Other value The constructor did not complete successfully.
112
113 **/
114 EFI_STATUS
115 EFIAPI
116 DxeDebugPrintErrorLevelLibConstructor (
117 IN EFI_HANDLE ImageHandle,
118 IN EFI_SYSTEM_TABLE *SystemTable
119 )
120 {
121 EFI_STATUS Status;
122
123 //
124 // Initialize the error level mask from PCD setting.
125 //
126 mDebugPrintErrorLevel = PcdGet32 (PcdDebugPrintErrorLevel);
127
128 //
129 // Install Debug Mask Protocol onto ImageHandle
130 //
131 mSystemTable = SystemTable;
132 Status = SystemTable->BootServices->InstallMultipleProtocolInterfaces (
133 &ImageHandle,
134 &gEfiDebugMaskProtocolGuid,
135 &mDebugMaskProtocol,
136 NULL
137 );
138
139 //
140 // Attempt to retrieve the global debug print error level mask from the EFI Variable
141 // If the EFI Variable can not be accessed when this module's library constructors are
142 // executed a HOB can be used to set the global debug print error level. If no value
143 // was found then the EFI Variable access will be reattempted on every DEBUG() print
144 // from this module until the EFI Variable services are available.
145 //
146 GetDebugPrintErrorLevel ();
147
148 return Status;
149 }
150
151 /**
152 The destructor function frees any allocated buffers and closes the Set Virtual
153 Address Map event.
154
155 @param ImageHandle The firmware allocated handle for the EFI image.
156 @param SystemTable A pointer to the EFI System Table.
157
158 @retval EFI_SUCCESS The destructor completed successfully.
159 @retval Other value The destructor did not complete successfully.
160
161 **/
162 EFI_STATUS
163 EFIAPI
164 DxeDebugPrintErrorLevelLibDestructor (
165 IN EFI_HANDLE ImageHandle,
166 IN EFI_SYSTEM_TABLE *SystemTable
167 )
168 {
169 //
170 // Uninstall the Debug Mask Protocol from ImageHandle
171 //
172 return SystemTable->BootServices->UninstallMultipleProtocolInterfaces (
173 ImageHandle,
174 &gEfiDebugMaskProtocolGuid,
175 &mDebugMaskProtocol,
176 NULL
177 );
178 }
179
180 /**
181 Returns the debug print error level mask for the current module.
182
183 @return Debug print error level mask for the current module.
184
185 **/
186 UINT32
187 EFIAPI
188 GetDebugPrintErrorLevel (
189 VOID
190 )
191 {
192 EFI_STATUS Status;
193 EFI_TPL CurrentTpl;
194 UINTN Size;
195 UINTN GlobalErrorLevel;
196 VOID *Hob;
197
198 //
199 // If the constructor has not been executed yet, then just return the PCD value.
200 // This case should only occur if debug print is generated by a library
201 // constructor for this module
202 //
203 if (mSystemTable == NULL) {
204 return PcdGet32 (PcdDebugPrintErrorLevel);
205 }
206
207 //
208 // Check to see if an attempt has been made to retrieve the global debug print
209 // error level mask. Since this library instance stores the global debug print
210 // error level mask in an EFI Variable, the EFI Variable should only be accessed
211 // once to reduce the overhead of reading the EFI Variable on every debug print
212 //
213 if (!mGlobalErrorLevelInitialized) {
214 //
215 // Make sure the TPL Level is low enough for EFI Variable Services to be called
216 //
217 CurrentTpl = mSystemTable->BootServices->RaiseTPL (TPL_HIGH_LEVEL);
218 mSystemTable->BootServices->RestoreTPL (CurrentTpl);
219 if (CurrentTpl <= TPL_CALLBACK) {
220 //
221 // Attempt to retrieve the global debug print error level mask from the
222 // EFI Variable
223 //
224 Size = sizeof (GlobalErrorLevel);
225 Status = mSystemTable->RuntimeServices->GetVariable (
226 DEBUG_MASK_VARIABLE_NAME,
227 &gEfiGenericVariableGuid,
228 NULL,
229 &Size,
230 &GlobalErrorLevel
231 );
232 if (Status != EFI_NOT_AVAILABLE_YET) {
233 //
234 // If EFI Variable Services are available, then set a flag so the EFI
235 // Variable will not be read again by this module.
236 //
237 mGlobalErrorLevelInitialized = TRUE;
238 if (!EFI_ERROR (Status)) {
239 //
240 // If the EFI Varible exists, then set this module's module's mask to
241 // the global debug print error level mask value.
242 //
243 mDebugPrintErrorLevel = (UINT32)GlobalErrorLevel;
244 }
245 } else {
246 //
247 // If variable services are not yet available optionally get the global
248 // debug print error level mask from a HOB.
249 //
250 Hob = GetFirstGuidHob (&gEfiGenericVariableGuid);
251 if (Hob != NULL) {
252 if (GET_GUID_HOB_DATA_SIZE (Hob) == sizeof (UINT32)) {
253 mDebugPrintErrorLevel = *(UINT32 *)GET_GUID_HOB_DATA (Hob);
254 mGlobalErrorLevelInitialized = TRUE;
255 }
256 }
257 }
258 }
259 }
260
261 //
262 // Return the current mask value for this module.
263 //
264 return mDebugPrintErrorLevel;
265 }
266
267 /**
268 Sets the global debug print error level mask fpr the entire platform.
269
270 @param ErrorLevel Global debug print error level
271
272 @retval TRUE The debug print error level mask was sucessfully set.
273 @retval FALSE The debug print error level mask could not be set.
274
275 **/
276 BOOLEAN
277 EFIAPI
278 SetDebugPrintErrorLevel (
279 UINT32 ErrorLevel
280 )
281 {
282 EFI_STATUS Status;
283 EFI_TPL CurrentTpl;
284 UINTN Size;
285 UINTN GlobalErrorLevel;
286
287 //
288 // Make sure the constructor has been executed
289 //
290 if (mSystemTable != NULL) {
291 //
292 // Make sure the TPL Level is low enough for EFI Variable Services
293 //
294 CurrentTpl = mSystemTable->BootServices->RaiseTPL (TPL_HIGH_LEVEL);
295 mSystemTable->BootServices->RestoreTPL (CurrentTpl);
296 if (CurrentTpl <= TPL_CALLBACK) {
297 //
298 // Attempt to store the global debug print error level mask in an EFI Variable
299 //
300 GlobalErrorLevel = (UINTN)ErrorLevel;
301 Size = sizeof (GlobalErrorLevel);
302 Status = mSystemTable->RuntimeServices->SetVariable (
303 DEBUG_MASK_VARIABLE_NAME,
304 &gEfiGenericVariableGuid,
305 (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS),
306 Size,
307 &GlobalErrorLevel
308 );
309 if (!EFI_ERROR (Status)) {
310 //
311 // If the EFI Variable was updated, then update the mask value for this
312 // module and return TRUE.
313 //
314 mGlobalErrorLevelInitialized = TRUE;
315 mDebugPrintErrorLevel = ErrorLevel;
316 return TRUE;
317 }
318 }
319 }
320
321 //
322 // Return FALSE since the EFI Variable could not be updated.
323 //
324 return FALSE;
325 }
326
327 /**
328 Retrieves the current debug print error level mask for a module are returns
329 it in CurrentDebugMask.
330
331 @param This The protocol instance pointer.
332 @param CurrentDebugMask Pointer to the debug print error level mask that
333 is returned.
334
335 @retval EFI_SUCCESS The current debug print error level mask was
336 returned in CurrentDebugMask.
337 @retval EFI_INVALID_PARAMETER CurrentDebugMask is NULL.
338 @retval EFI_DEVICE_ERROR The current debug print error level mask could
339 not be retrieved.
340
341 **/
342 EFI_STATUS
343 EFIAPI
344 GetDebugMask (
345 IN EFI_DEBUG_MASK_PROTOCOL *This,
346 IN OUT UINTN *CurrentDebugMask
347 )
348 {
349 if (CurrentDebugMask == NULL) {
350 return EFI_INVALID_PARAMETER;
351 }
352
353 //
354 // Retrieve the current debug mask from mDebugPrintErrorLevel
355 //
356 *CurrentDebugMask = (UINTN)mDebugPrintErrorLevel;
357 return EFI_SUCCESS;
358 }
359
360 /**
361 Sets the current debug print error level mask for a module to the value
362 specified by NewDebugMask.
363
364 @param This The protocol instance pointer.
365 @param NewDebugMask The new debug print error level mask for this module.
366
367 @retval EFI_SUCCESS The current debug print error level mask was
368 set to the value specified by NewDebugMask.
369 @retval EFI_DEVICE_ERROR The current debug print error level mask could
370 not be set to the value specified by NewDebugMask.
371
372 **/
373 EFI_STATUS
374 EFIAPI
375 SetDebugMask (
376 IN EFI_DEBUG_MASK_PROTOCOL *This,
377 IN UINTN NewDebugMask
378 )
379 {
380 //
381 // Store the new debug mask into mDebugPrintErrorLevel
382 //
383 mDebugPrintErrorLevel = (UINT32)NewDebugMask;
384 return EFI_SUCCESS;
385 }