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