TianoCore EDK2 master
Loading...
Searching...
No Matches
StatusCodeHandler.c
Go to the documentation of this file.
1
22#include <Library/DebugLib.h>
25#include <Library/PcdLib.h>
26#include <Library/PrintLib.h>
29#include <Library/UefiLib.h>
31
33
34#include <Guid/GlobalVariable.h>
36
37#include <Pi/PiStatusCode.h>
38
39//
40// Convenience variables for the status codes that are relevant for LoadImage()
41// and StartImage() preparations and return codes.
42//
47
78EFIAPI
80 IN EFI_STATUS_CODE_TYPE CodeType,
82 IN UINT32 Instance,
83 IN EFI_GUID *CallerId,
85 )
86{
87 UINTN VariableSize;
88 UINT16 BootCurrent;
89 EFI_STATUS Status;
90 CHAR16 BootOptionName[ARRAY_SIZE (L"Boot####")];
92 BOOLEAN DevPathStringIsDynamic;
93 CHAR16 *DevPathString;
94
95 //
96 // Ignore all status codes that are irrelevant for LoadImage() and
97 // StartImage() preparations and return codes.
98 //
99 if ((Value != mLoadPrep) && (Value != mLoadFail) &&
100 (Value != mStartPrep) && (Value != mStartFail))
101 {
102 return EFI_SUCCESS;
103 }
104
105 //
106 // Ignore status codes that are not reported by the same containing module.
107 //
108 if (!CompareGuid (CallerId, &gEfiCallerIdGuid)) {
109 return EFI_SUCCESS;
110 }
111
112 //
113 // Sanity-check Data in case of failure reports.
114 //
115 if (((Value == mLoadFail) || (Value == mStartFail)) &&
116 ((Data == NULL) ||
117 (Data->HeaderSize != sizeof *Data) ||
118 (Data->Size != sizeof (EFI_RETURN_STATUS_EXTENDED_DATA) - sizeof *Data) ||
119 !CompareGuid (&Data->Type, &gEfiStatusCodeSpecificDataGuid)))
120 {
121 DEBUG ((
122 DEBUG_ERROR,
123 "%a:%a: malformed Data\n",
124 gEfiCallerBaseName,
125 __func__
126 ));
127 return EFI_INVALID_PARAMETER;
128 }
129
130 //
131 // Get the number of the Boot#### option that the status code applies to.
132 //
133 VariableSize = sizeof BootCurrent;
134 Status = gRT->GetVariable (
136 &gEfiGlobalVariableGuid,
137 NULL /* Attributes */,
138 &VariableSize,
139 &BootCurrent
140 );
141 if (EFI_ERROR (Status)) {
142 DEBUG ((
143 DEBUG_ERROR,
144 "%a:%a: failed to get %g:\"%s\": %r\n",
145 gEfiCallerBaseName,
146 __func__,
147 &gEfiGlobalVariableGuid,
149 Status
150 ));
151 return Status;
152 }
153
154 if (VariableSize != sizeof BootCurrent) {
155 DEBUG ((
156 DEBUG_ERROR,
157 "%a:%a: got %Lu bytes for %g:\"%s\", expected %Lu\n",
158 gEfiCallerBaseName,
159 __func__,
160 (UINT64)VariableSize,
161 &gEfiGlobalVariableGuid,
163 (UINT64)sizeof BootCurrent
164 ));
165 return EFI_INCOMPATIBLE_VERSION;
166 }
167
168 //
169 // Get the Boot#### option that the status code applies to.
170 //
172 BootOptionName,
173 sizeof BootOptionName,
174 L"Boot%04x",
175 BootCurrent
176 );
177 Status = EfiBootManagerVariableToLoadOption (BootOptionName, &BmBootOption);
178 if (EFI_ERROR (Status)) {
179 DEBUG ((
180 DEBUG_ERROR,
181 "%a:%a: EfiBootManagerVariableToLoadOption(\"%s\"): %r\n",
182 gEfiCallerBaseName,
183 __func__,
184 BootOptionName,
185 Status
186 ));
187 return Status;
188 }
189
190 //
191 // Format the device path.
192 //
193 DevPathStringIsDynamic = TRUE;
194 DevPathString = ConvertDevicePathToText (
195 BmBootOption.FilePath,
196 FALSE, // DisplayOnly
197 FALSE // AllowShortcuts
198 );
199 if (DevPathString == NULL) {
200 DevPathStringIsDynamic = FALSE;
201 DevPathString = L"<out of memory while formatting device path>";
202 }
203
204 //
205 // Print the message to the console.
206 //
207 if ((Value == mLoadPrep) || (Value == mStartPrep)) {
208 Print (
209 L"%a: %a %s \"%s\" from %s\n",
210 gEfiCallerBaseName,
211 Value == mLoadPrep ? "loading" : "starting",
212 BootOptionName,
213 BmBootOption.Description,
214 DevPathString
215 );
216 } else {
217 Print (
218 L"%a: failed to %a %s \"%s\" from %s: %r\n",
219 gEfiCallerBaseName,
220 Value == mLoadFail ? "load" : "start",
221 BootOptionName,
222 BmBootOption.Description,
223 DevPathString,
224 ((EFI_RETURN_STATUS_EXTENDED_DATA *)Data)->ReturnStatus
225 );
226 }
227
228 //
229 // Done.
230 //
231 if (DevPathStringIsDynamic) {
232 FreePool (DevPathString);
233 }
234
235 EfiBootManagerFreeLoadOption (&BmBootOption);
236 return EFI_SUCCESS;
237}
238
249STATIC
250VOID
251EFIAPI
253 IN EFI_EVENT Event,
254 IN VOID *Context
255 )
256{
257 EFI_RSC_HANDLER_PROTOCOL *StatusCodeRouter;
258
259 StatusCodeRouter = Context;
260 StatusCodeRouter->Unregister (HandleStatusCode);
261}
262
274EFIAPI
276 VOID
277 )
278{
279 EFI_STATUS Status;
280 EFI_RSC_HANDLER_PROTOCOL *StatusCodeRouter;
281 EFI_EVENT ExitBootEvent;
282
283 Status = gBS->LocateProtocol (
284 &gEfiRscHandlerProtocolGuid,
285 NULL /* Registration */,
286 (VOID **)&StatusCodeRouter
287 );
288 ASSERT_EFI_ERROR (Status);
289 if (EFI_ERROR (Status)) {
290 return Status;
291 }
292
293 //
294 // Set the EFI_STATUS_CODE_VALUE convenience variables.
295 //
296 mLoadPrep = PcdGet32 (PcdProgressCodeOsLoaderLoad);
297 mLoadFail = (EFI_SOFTWARE_DXE_BS_DRIVER |
298 EFI_SW_DXE_BS_EC_BOOT_OPTION_LOAD_ERROR);
299 mStartPrep = PcdGet32 (PcdProgressCodeOsLoaderStart);
300 mStartFail = (EFI_SOFTWARE_DXE_BS_DRIVER |
301 EFI_SW_DXE_BS_EC_BOOT_OPTION_FAILED);
302
303 //
304 // Register the handler callback.
305 //
306 Status = StatusCodeRouter->Register (HandleStatusCode, TPL_CALLBACK);
307 if (EFI_ERROR (Status)) {
308 DEBUG ((
309 DEBUG_ERROR,
310 "%a:%a: failed to register status code handler: %r\n",
311 gEfiCallerBaseName,
312 __func__,
313 Status
314 ));
315 return Status;
316 }
317
318 //
319 // Status code reporting and routing/handling extend into OS runtime. Since
320 // we don't want our handler to survive the BDS phase, we have to unregister
321 // the callback at ExitBootServices(). (See EFI_RSC_HANDLER_PROTOCOL in
322 // Volume 3 of the Platform Init spec.)
323 //
324 Status = gBS->CreateEvent (
325 EVT_SIGNAL_EXIT_BOOT_SERVICES, // Type
326 TPL_CALLBACK, // NotifyTpl
327 UnregisterAtExitBootServices, // NotifyFunction
328 StatusCodeRouter, // NotifyContext
329 &ExitBootEvent // Event
330 );
331 if (EFI_ERROR (Status)) {
332 //
333 // We have to unregister the callback right now, and fail the function.
334 //
335 DEBUG ((
336 DEBUG_ERROR,
337 "%a:%a: failed to create ExitBootServices() event: "
338 "%r\n",
339 gEfiCallerBaseName,
340 __func__,
341 Status
342 ));
343 StatusCodeRouter->Unregister (HandleStatusCode);
344 return Status;
345 }
346
347 return EFI_SUCCESS;
348}
UINT64 UINTN
BOOLEAN EFIAPI CompareGuid(IN CONST GUID *Guid1, IN CONST GUID *Guid2)
Definition: MemLibGuid.c:73
CHAR16 *EFIAPI ConvertDevicePathToText(IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath, IN BOOLEAN DisplayOnly, IN BOOLEAN AllowShortcuts)
VOID EFIAPI FreePool(IN VOID *Buffer)
#define EFI_BOOT_CURRENT_VARIABLE_NAME
UINTN EFIAPI UnicodeSPrint(OUT CHAR16 *StartOfBuffer, IN UINTN BufferSize, IN CONST CHAR16 *FormatString,...)
Definition: PrintLib.c:408
EFI_RUNTIME_SERVICES * gRT
#define NULL
Definition: Base.h:319
#define STATIC
Definition: Base.h:264
#define TRUE
Definition: Base.h:301
#define FALSE
Definition: Base.h:307
#define ARRAY_SIZE(Array)
Definition: Base.h:1393
#define IN
Definition: Base.h:279
#define ASSERT_EFI_ERROR(StatusParameter)
Definition: DebugLib.h:462
#define DEBUG(Expression)
Definition: DebugLib.h:434
#define PcdGet32(TokenName)
Definition: PcdLib.h:362
UINT32 EFI_STATUS_CODE_VALUE
Definition: PiStatusCode.h:67
UINT32 EFI_STATUS_CODE_TYPE
Definition: PiStatusCode.h:24
STATIC EFI_STATUS EFIAPI HandleStatusCode(IN EFI_STATUS_CODE_TYPE CodeType, IN EFI_STATUS_CODE_VALUE Value, IN UINT32 Instance, IN EFI_GUID *CallerId, IN EFI_STATUS_CODE_DATA *Data)
EFI_STATUS EFIAPI PlatformBmPrintScRegisterHandler(VOID)
STATIC VOID EFIAPI UnregisterAtExitBootServices(IN EFI_EVENT Event, IN VOID *Context)
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
VOID * EFI_EVENT
Definition: UefiBaseType.h:37
#define EFI_SUCCESS
Definition: UefiBaseType.h:112
EFI_STATUS EFIAPI EfiBootManagerFreeLoadOption(IN EFI_BOOT_MANAGER_LOAD_OPTION *LoadOption)
EFI_STATUS EFIAPI EfiBootManagerVariableToLoadOption(IN CHAR16 *VariableName, IN OUT EFI_BOOT_MANAGER_LOAD_OPTION *LoadOption)
Definition: BmLoadOption.c:998
EFI_BOOT_SERVICES * gBS
UINTN EFIAPI Print(IN CONST CHAR16 *Format,...)
Definition: UefiLibPrint.c:113
Definition: Base.h:213