]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Library/DxeDebugPrintErrorLevelLib/DxeDebugPrintErrorLevelLib.c
MdeModulePkg: Replace BSD License with BSD+Patent License
[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, &mDebugMaskProtocol,
135 NULL
136 );
137
138 //
139 // Attempt to retrieve the global debug print error level mask from the EFI Variable
140 // If the EFI Variable can not be accessed when this module's library constructors are
141 // executed a HOB can be used to set the global debug print error level. If no value
142 // was found then the EFI Variable access will be reattempted on every DEBUG() print
143 // from this module until the EFI Variable services are available.
144 //
145 GetDebugPrintErrorLevel ();
146
147 return Status;
148 }
149
150 /**
151 The destructor function frees any allocated buffers and closes the Set Virtual
152 Address Map event.
153
154 @param ImageHandle The firmware allocated handle for the EFI image.
155 @param SystemTable A pointer to the EFI System Table.
156
157 @retval EFI_SUCCESS The destructor completed successfully.
158 @retval Other value The destructor did not complete successfully.
159
160 **/
161 EFI_STATUS
162 EFIAPI
163 DxeDebugPrintErrorLevelLibDestructor (
164 IN EFI_HANDLE ImageHandle,
165 IN EFI_SYSTEM_TABLE *SystemTable
166 )
167 {
168 //
169 // Uninstall the Debug Mask Protocol from ImageHandle
170 //
171 return SystemTable->BootServices->UninstallMultipleProtocolInterfaces (
172 ImageHandle,
173 &gEfiDebugMaskProtocolGuid, &mDebugMaskProtocol,
174 NULL
175 );
176 }
177
178 /**
179 Returns the debug print error level mask for the current module.
180
181 @return Debug print error level mask for the current module.
182
183 **/
184 UINT32
185 EFIAPI
186 GetDebugPrintErrorLevel (
187 VOID
188 )
189 {
190 EFI_STATUS Status;
191 EFI_TPL CurrentTpl;
192 UINTN Size;
193 UINTN GlobalErrorLevel;
194 VOID *Hob;
195
196 //
197 // If the constructor has not been executed yet, then just return the PCD value.
198 // This case should only occur if debug print is generated by a library
199 // constructor for this module
200 //
201 if (mSystemTable == NULL) {
202 return PcdGet32 (PcdDebugPrintErrorLevel);
203 }
204
205 //
206 // Check to see if an attempt has been made to retrieve the global debug print
207 // error level mask. Since this library instance stores the global debug print
208 // error level mask in an EFI Variable, the EFI Variable should only be accessed
209 // once to reduce the overhead of reading the EFI Variable on every debug print
210 //
211 if (!mGlobalErrorLevelInitialized) {
212 //
213 // Make sure the TPL Level is low enough for EFI Variable Services to be called
214 //
215 CurrentTpl = mSystemTable->BootServices->RaiseTPL (TPL_HIGH_LEVEL);
216 mSystemTable->BootServices->RestoreTPL (CurrentTpl);
217 if (CurrentTpl <= TPL_CALLBACK) {
218 //
219 // Attempt to retrieve the global debug print error level mask from the
220 // EFI Variable
221 //
222 Size = sizeof (GlobalErrorLevel);
223 Status = mSystemTable->RuntimeServices->GetVariable (
224 DEBUG_MASK_VARIABLE_NAME,
225 &gEfiGenericVariableGuid,
226 NULL,
227 &Size,
228 &GlobalErrorLevel
229 );
230 if (Status != EFI_NOT_AVAILABLE_YET) {
231 //
232 // If EFI Variable Services are available, then set a flag so the EFI
233 // Variable will not be read again by this module.
234 //
235 mGlobalErrorLevelInitialized = TRUE;
236 if (!EFI_ERROR (Status)) {
237 //
238 // If the EFI Varible exists, then set this module's module's mask to
239 // the global debug print error level mask value.
240 //
241 mDebugPrintErrorLevel = (UINT32)GlobalErrorLevel;
242 }
243 } else {
244 //
245 // If variable services are not yet available optionally get the global
246 // debug print error level mask from a HOB.
247 //
248 Hob = GetFirstGuidHob (&gEfiGenericVariableGuid);
249 if (Hob != NULL) {
250 if (GET_GUID_HOB_DATA_SIZE (Hob) == sizeof (UINT32)) {
251 mDebugPrintErrorLevel = *(UINT32 *)GET_GUID_HOB_DATA (Hob);
252 mGlobalErrorLevelInitialized = TRUE;
253 }
254 }
255 }
256 }
257 }
258
259 //
260 // Return the current mask value for this module.
261 //
262 return mDebugPrintErrorLevel;
263 }
264
265 /**
266 Sets the global debug print error level mask fpr the entire platform.
267
268 @param ErrorLevel Global debug print error level
269
270 @retval TRUE The debug print error level mask was sucessfully set.
271 @retval FALSE The debug print error level mask could not be set.
272
273 **/
274 BOOLEAN
275 EFIAPI
276 SetDebugPrintErrorLevel (
277 UINT32 ErrorLevel
278 )
279 {
280 EFI_STATUS Status;
281 EFI_TPL CurrentTpl;
282 UINTN Size;
283 UINTN GlobalErrorLevel;
284
285 //
286 // Make sure the constructor has been executed
287 //
288 if (mSystemTable != NULL) {
289 //
290 // Make sure the TPL Level is low enough for EFI Variable Services
291 //
292 CurrentTpl = mSystemTable->BootServices->RaiseTPL (TPL_HIGH_LEVEL);
293 mSystemTable->BootServices->RestoreTPL (CurrentTpl);
294 if (CurrentTpl <= TPL_CALLBACK) {
295 //
296 // Attempt to store the global debug print error level mask in an EFI Variable
297 //
298 GlobalErrorLevel = (UINTN)ErrorLevel;
299 Size = sizeof (GlobalErrorLevel);
300 Status = mSystemTable->RuntimeServices->SetVariable (
301 DEBUG_MASK_VARIABLE_NAME,
302 &gEfiGenericVariableGuid,
303 (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS),
304 Size,
305 &GlobalErrorLevel
306 );
307 if (!EFI_ERROR (Status)) {
308 //
309 // If the EFI Variable was updated, then update the mask value for this
310 // module and return TRUE.
311 //
312 mGlobalErrorLevelInitialized = TRUE;
313 mDebugPrintErrorLevel = ErrorLevel;
314 return TRUE;
315 }
316 }
317 }
318 //
319 // Return FALSE since the EFI Variable could not be updated.
320 //
321 return FALSE;
322 }
323
324 /**
325 Retrieves the current debug print error level mask for a module are returns
326 it in CurrentDebugMask.
327
328 @param This The protocol instance pointer.
329 @param CurrentDebugMask Pointer to the debug print error level mask that
330 is returned.
331
332 @retval EFI_SUCCESS The current debug print error level mask was
333 returned in CurrentDebugMask.
334 @retval EFI_INVALID_PARAMETER CurrentDebugMask is NULL.
335 @retval EFI_DEVICE_ERROR The current debug print error level mask could
336 not be retrieved.
337
338 **/
339 EFI_STATUS
340 EFIAPI
341 GetDebugMask (
342 IN EFI_DEBUG_MASK_PROTOCOL *This,
343 IN OUT UINTN *CurrentDebugMask
344 )
345 {
346 if (CurrentDebugMask == NULL) {
347 return EFI_INVALID_PARAMETER;
348 }
349
350 //
351 // Retrieve the current debug mask from mDebugPrintErrorLevel
352 //
353 *CurrentDebugMask = (UINTN)mDebugPrintErrorLevel;
354 return EFI_SUCCESS;
355 }
356
357 /**
358 Sets the current debug print error level mask for a module to the value
359 specified by NewDebugMask.
360
361 @param This The protocol instance pointer.
362 @param NewDebugMask The new debug print error level mask for this module.
363
364 @retval EFI_SUCCESS The current debug print error level mask was
365 set to the value specified by NewDebugMask.
366 @retval EFI_DEVICE_ERROR The current debug print error level mask could
367 not be set to the value specified by NewDebugMask.
368
369 **/
370 EFI_STATUS
371 EFIAPI
372 SetDebugMask (
373 IN EFI_DEBUG_MASK_PROTOCOL *This,
374 IN UINTN NewDebugMask
375 )
376 {
377 //
378 // Store the new debug mask into mDebugPrintErrorLevel
379 //
380 mDebugPrintErrorLevel = (UINT32)NewDebugMask;
381 return EFI_SUCCESS;
382 }