]> git.proxmox.com Git - mirror_edk2.git/blame - ArmPkg/Library/PlatformBootManagerLib/PlatformBm.c
ArmPkg/PlatformBootManagerLib: reject 'default' parity and stop bit count
[mirror_edk2.git] / ArmPkg / Library / PlatformBootManagerLib / PlatformBm.c
CommitLineData
c976f9cb
AB
1/** @file\r
2 Implementation for PlatformBootManagerLib library class interfaces.\r
3\r
4 Copyright (C) 2015-2016, Red Hat, Inc.\r
0f9395d7 5 Copyright (c) 2014 - 2019, ARM Ltd. All rights reserved.<BR>\r
eea668c9 6 Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>\r
c976f9cb
AB
7 Copyright (c) 2016, Linaro Ltd. All rights reserved.<BR>\r
8\r
4059386c 9 SPDX-License-Identifier: BSD-2-Clause-Patent\r
c976f9cb
AB
10\r
11**/\r
12\r
13#include <IndustryStandard/Pci22.h>\r
a43d75e1 14#include <Library/BootLogoLib.h>\r
4bbcc285 15#include <Library/CapsuleLib.h>\r
c976f9cb 16#include <Library/DevicePathLib.h>\r
4bbcc285 17#include <Library/HobLib.h>\r
c976f9cb
AB
18#include <Library/PcdLib.h>\r
19#include <Library/UefiBootManagerLib.h>\r
20#include <Library/UefiLib.h>\r
cae82316 21#include <Library/UefiRuntimeServicesTableLib.h>\r
c976f9cb 22#include <Protocol/DevicePath.h>\r
13ca0abb 23#include <Protocol/EsrtManagement.h>\r
c976f9cb
AB
24#include <Protocol/GraphicsOutput.h>\r
25#include <Protocol/LoadedImage.h>\r
26#include <Protocol/PciIo.h>\r
27#include <Protocol/PciRootBridgeIo.h>\r
1b6e7633 28#include <Protocol/PlatformBootManager.h>\r
c976f9cb
AB
29#include <Guid/EventGroup.h>\r
30#include <Guid/TtyTerm.h>\r
6631c096 31#include <Guid/SerialPortLibVendor.h>\r
c976f9cb
AB
32\r
33#include "PlatformBm.h"\r
34\r
35#define DP_NODE_LEN(Type) { (UINT8)sizeof (Type), (UINT8)(sizeof (Type) >> 8) }\r
36\r
c976f9cb
AB
37#pragma pack (1)\r
38typedef struct {\r
39 VENDOR_DEVICE_PATH SerialDxe;\r
40 UART_DEVICE_PATH Uart;\r
41 VENDOR_DEFINED_DEVICE_PATH TermType;\r
42 EFI_DEVICE_PATH_PROTOCOL End;\r
43} PLATFORM_SERIAL_CONSOLE;\r
44#pragma pack ()\r
45\r
c976f9cb
AB
46STATIC PLATFORM_SERIAL_CONSOLE mSerialConsole = {\r
47 //\r
48 // VENDOR_DEVICE_PATH SerialDxe\r
49 //\r
50 {\r
51 { HARDWARE_DEVICE_PATH, HW_VENDOR_DP, DP_NODE_LEN (VENDOR_DEVICE_PATH) },\r
6631c096 52 EDKII_SERIAL_PORT_LIB_VENDOR_GUID\r
c976f9cb
AB
53 },\r
54\r
55 //\r
56 // UART_DEVICE_PATH Uart\r
57 //\r
58 {\r
59 { MESSAGING_DEVICE_PATH, MSG_UART_DP, DP_NODE_LEN (UART_DEVICE_PATH) },\r
60 0, // Reserved\r
61 FixedPcdGet64 (PcdUartDefaultBaudRate), // BaudRate\r
62 FixedPcdGet8 (PcdUartDefaultDataBits), // DataBits\r
63 FixedPcdGet8 (PcdUartDefaultParity), // Parity\r
64 FixedPcdGet8 (PcdUartDefaultStopBits) // StopBits\r
65 },\r
66\r
67 //\r
68 // VENDOR_DEFINED_DEVICE_PATH TermType\r
69 //\r
70 {\r
71 {\r
72 MESSAGING_DEVICE_PATH, MSG_VENDOR_DP,\r
73 DP_NODE_LEN (VENDOR_DEFINED_DEVICE_PATH)\r
74 }\r
75 //\r
76 // Guid to be filled in dynamically\r
77 //\r
78 },\r
79\r
80 //\r
81 // EFI_DEVICE_PATH_PROTOCOL End\r
82 //\r
83 {\r
84 END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE,\r
85 DP_NODE_LEN (EFI_DEVICE_PATH_PROTOCOL)\r
86 }\r
87};\r
88\r
89\r
90#pragma pack (1)\r
91typedef struct {\r
92 USB_CLASS_DEVICE_PATH Keyboard;\r
93 EFI_DEVICE_PATH_PROTOCOL End;\r
94} PLATFORM_USB_KEYBOARD;\r
95#pragma pack ()\r
96\r
97STATIC PLATFORM_USB_KEYBOARD mUsbKeyboard = {\r
98 //\r
99 // USB_CLASS_DEVICE_PATH Keyboard\r
100 //\r
101 {\r
102 {\r
103 MESSAGING_DEVICE_PATH, MSG_USB_CLASS_DP,\r
104 DP_NODE_LEN (USB_CLASS_DEVICE_PATH)\r
105 },\r
106 0xFFFF, // VendorId: any\r
107 0xFFFF, // ProductId: any\r
108 3, // DeviceClass: HID\r
109 1, // DeviceSubClass: boot\r
110 1 // DeviceProtocol: keyboard\r
111 },\r
112\r
113 //\r
114 // EFI_DEVICE_PATH_PROTOCOL End\r
115 //\r
116 {\r
117 END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE,\r
118 DP_NODE_LEN (EFI_DEVICE_PATH_PROTOCOL)\r
119 }\r
120};\r
121\r
122\r
123/**\r
124 Check if the handle satisfies a particular condition.\r
125\r
126 @param[in] Handle The handle to check.\r
127 @param[in] ReportText A caller-allocated string passed in for reporting\r
128 purposes. It must never be NULL.\r
129\r
130 @retval TRUE The condition is satisfied.\r
131 @retval FALSE Otherwise. This includes the case when the condition could not\r
132 be fully evaluated due to an error.\r
133**/\r
134typedef\r
135BOOLEAN\r
136(EFIAPI *FILTER_FUNCTION) (\r
137 IN EFI_HANDLE Handle,\r
138 IN CONST CHAR16 *ReportText\r
139 );\r
140\r
141\r
142/**\r
143 Process a handle.\r
144\r
145 @param[in] Handle The handle to process.\r
146 @param[in] ReportText A caller-allocated string passed in for reporting\r
147 purposes. It must never be NULL.\r
148**/\r
149typedef\r
150VOID\r
151(EFIAPI *CALLBACK_FUNCTION) (\r
152 IN EFI_HANDLE Handle,\r
153 IN CONST CHAR16 *ReportText\r
154 );\r
155\r
156/**\r
157 Locate all handles that carry the specified protocol, filter them with a\r
158 callback function, and pass each handle that passes the filter to another\r
159 callback.\r
160\r
161 @param[in] ProtocolGuid The protocol to look for.\r
162\r
163 @param[in] Filter The filter function to pass each handle to. If this\r
164 parameter is NULL, then all handles are processed.\r
165\r
166 @param[in] Process The callback function to pass each handle to that\r
167 clears the filter.\r
168**/\r
169STATIC\r
170VOID\r
171FilterAndProcess (\r
172 IN EFI_GUID *ProtocolGuid,\r
173 IN FILTER_FUNCTION Filter OPTIONAL,\r
174 IN CALLBACK_FUNCTION Process\r
175 )\r
176{\r
177 EFI_STATUS Status;\r
178 EFI_HANDLE *Handles;\r
179 UINTN NoHandles;\r
180 UINTN Idx;\r
181\r
182 Status = gBS->LocateHandleBuffer (ByProtocol, ProtocolGuid,\r
183 NULL /* SearchKey */, &NoHandles, &Handles);\r
184 if (EFI_ERROR (Status)) {\r
185 //\r
186 // This is not an error, just an informative condition.\r
187 //\r
188 DEBUG ((EFI_D_VERBOSE, "%a: %g: %r\n", __FUNCTION__, ProtocolGuid,\r
189 Status));\r
190 return;\r
191 }\r
192\r
193 ASSERT (NoHandles > 0);\r
194 for (Idx = 0; Idx < NoHandles; ++Idx) {\r
195 CHAR16 *DevicePathText;\r
196 STATIC CHAR16 Fallback[] = L"<device path unavailable>";\r
197\r
198 //\r
199 // The ConvertDevicePathToText() function handles NULL input transparently.\r
200 //\r
201 DevicePathText = ConvertDevicePathToText (\r
202 DevicePathFromHandle (Handles[Idx]),\r
203 FALSE, // DisplayOnly\r
204 FALSE // AllowShortcuts\r
205 );\r
206 if (DevicePathText == NULL) {\r
207 DevicePathText = Fallback;\r
208 }\r
209\r
210 if (Filter == NULL || Filter (Handles[Idx], DevicePathText)) {\r
211 Process (Handles[Idx], DevicePathText);\r
212 }\r
213\r
214 if (DevicePathText != Fallback) {\r
215 FreePool (DevicePathText);\r
216 }\r
217 }\r
218 gBS->FreePool (Handles);\r
219}\r
220\r
221\r
222/**\r
223 This FILTER_FUNCTION checks if a handle corresponds to a PCI display device.\r
224**/\r
225STATIC\r
226BOOLEAN\r
227EFIAPI\r
228IsPciDisplay (\r
229 IN EFI_HANDLE Handle,\r
230 IN CONST CHAR16 *ReportText\r
231 )\r
232{\r
233 EFI_STATUS Status;\r
234 EFI_PCI_IO_PROTOCOL *PciIo;\r
235 PCI_TYPE00 Pci;\r
236\r
237 Status = gBS->HandleProtocol (Handle, &gEfiPciIoProtocolGuid,\r
238 (VOID**)&PciIo);\r
239 if (EFI_ERROR (Status)) {\r
240 //\r
241 // This is not an error worth reporting.\r
242 //\r
243 return FALSE;\r
244 }\r
245\r
246 Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, 0 /* Offset */,\r
247 sizeof Pci / sizeof (UINT32), &Pci);\r
248 if (EFI_ERROR (Status)) {\r
249 DEBUG ((EFI_D_ERROR, "%a: %s: %r\n", __FUNCTION__, ReportText, Status));\r
250 return FALSE;\r
251 }\r
252\r
253 return IS_PCI_DISPLAY (&Pci);\r
254}\r
255\r
256\r
257/**\r
258 This CALLBACK_FUNCTION attempts to connect a handle non-recursively, asking\r
259 the matching driver to produce all first-level child handles.\r
260**/\r
261STATIC\r
262VOID\r
263EFIAPI\r
264Connect (\r
265 IN EFI_HANDLE Handle,\r
266 IN CONST CHAR16 *ReportText\r
267 )\r
268{\r
269 EFI_STATUS Status;\r
270\r
271 Status = gBS->ConnectController (\r
272 Handle, // ControllerHandle\r
273 NULL, // DriverImageHandle\r
274 NULL, // RemainingDevicePath -- produce all children\r
275 FALSE // Recursive\r
276 );\r
277 DEBUG ((EFI_ERROR (Status) ? EFI_D_ERROR : EFI_D_VERBOSE, "%a: %s: %r\n",\r
278 __FUNCTION__, ReportText, Status));\r
279}\r
280\r
281\r
282/**\r
283 This CALLBACK_FUNCTION retrieves the EFI_DEVICE_PATH_PROTOCOL from the\r
284 handle, and adds it to ConOut and ErrOut.\r
285**/\r
286STATIC\r
287VOID\r
288EFIAPI\r
289AddOutput (\r
290 IN EFI_HANDLE Handle,\r
291 IN CONST CHAR16 *ReportText\r
292 )\r
293{\r
294 EFI_STATUS Status;\r
295 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
296\r
297 DevicePath = DevicePathFromHandle (Handle);\r
298 if (DevicePath == NULL) {\r
299 DEBUG ((EFI_D_ERROR, "%a: %s: handle %p: device path not found\n",\r
300 __FUNCTION__, ReportText, Handle));\r
301 return;\r
302 }\r
303\r
304 Status = EfiBootManagerUpdateConsoleVariable (ConOut, DevicePath, NULL);\r
305 if (EFI_ERROR (Status)) {\r
306 DEBUG ((EFI_D_ERROR, "%a: %s: adding to ConOut: %r\n", __FUNCTION__,\r
307 ReportText, Status));\r
308 return;\r
309 }\r
310\r
311 Status = EfiBootManagerUpdateConsoleVariable (ErrOut, DevicePath, NULL);\r
312 if (EFI_ERROR (Status)) {\r
313 DEBUG ((EFI_D_ERROR, "%a: %s: adding to ErrOut: %r\n", __FUNCTION__,\r
314 ReportText, Status));\r
315 return;\r
316 }\r
317\r
318 DEBUG ((EFI_D_VERBOSE, "%a: %s: added to ConOut and ErrOut\n", __FUNCTION__,\r
319 ReportText));\r
320}\r
321\r
322STATIC\r
323VOID\r
324PlatformRegisterFvBootOption (\r
07548e17 325 CONST EFI_GUID *FileGuid,\r
c976f9cb
AB
326 CHAR16 *Description,\r
327 UINT32 Attributes\r
328 )\r
329{\r
330 EFI_STATUS Status;\r
331 INTN OptionIndex;\r
332 EFI_BOOT_MANAGER_LOAD_OPTION NewOption;\r
333 EFI_BOOT_MANAGER_LOAD_OPTION *BootOptions;\r
334 UINTN BootOptionCount;\r
335 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH FileNode;\r
336 EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;\r
337 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
338\r
339 Status = gBS->HandleProtocol (\r
340 gImageHandle,\r
341 &gEfiLoadedImageProtocolGuid,\r
342 (VOID **) &LoadedImage\r
343 );\r
344 ASSERT_EFI_ERROR (Status);\r
345\r
346 EfiInitializeFwVolDevicepathNode (&FileNode, FileGuid);\r
347 DevicePath = DevicePathFromHandle (LoadedImage->DeviceHandle);\r
348 ASSERT (DevicePath != NULL);\r
349 DevicePath = AppendDevicePathNode (\r
350 DevicePath,\r
351 (EFI_DEVICE_PATH_PROTOCOL *) &FileNode\r
352 );\r
353 ASSERT (DevicePath != NULL);\r
354\r
355 Status = EfiBootManagerInitializeLoadOption (\r
356 &NewOption,\r
357 LoadOptionNumberUnassigned,\r
358 LoadOptionTypeBoot,\r
359 Attributes,\r
360 Description,\r
361 DevicePath,\r
362 NULL,\r
363 0\r
364 );\r
365 ASSERT_EFI_ERROR (Status);\r
366 FreePool (DevicePath);\r
367\r
368 BootOptions = EfiBootManagerGetLoadOptions (\r
369 &BootOptionCount, LoadOptionTypeBoot\r
370 );\r
371\r
372 OptionIndex = EfiBootManagerFindLoadOption (\r
373 &NewOption, BootOptions, BootOptionCount\r
374 );\r
375\r
376 if (OptionIndex == -1) {\r
377 Status = EfiBootManagerAddLoadOptionVariable (&NewOption, MAX_UINTN);\r
378 ASSERT_EFI_ERROR (Status);\r
379 }\r
380 EfiBootManagerFreeLoadOption (&NewOption);\r
381 EfiBootManagerFreeLoadOptions (BootOptions, BootOptionCount);\r
382}\r
383\r
384\r
1b6e7633
HZ
385STATIC\r
386VOID\r
387GetPlatformOptions (\r
388 VOID\r
389 )\r
390{\r
391 EFI_STATUS Status;\r
392 EFI_BOOT_MANAGER_LOAD_OPTION *CurrentBootOptions;\r
393 EFI_BOOT_MANAGER_LOAD_OPTION *BootOptions;\r
394 EFI_INPUT_KEY *BootKeys;\r
395 PLATFORM_BOOT_MANAGER_PROTOCOL *PlatformBootManager;\r
396 UINTN CurrentBootOptionCount;\r
397 UINTN Index;\r
398 UINTN BootCount;\r
399\r
400 Status = gBS->LocateProtocol (&gPlatformBootManagerProtocolGuid, NULL,\r
401 (VOID **)&PlatformBootManager);\r
402 if (EFI_ERROR (Status)) {\r
403 return;\r
404 }\r
405 Status = PlatformBootManager->GetPlatformBootOptionsAndKeys (\r
406 &BootCount,\r
407 &BootOptions,\r
408 &BootKeys\r
409 );\r
410 if (EFI_ERROR (Status)) {\r
411 return;\r
412 }\r
413 //\r
414 // Fetch the existent boot options. If there are none, CurrentBootCount\r
415 // will be zeroed.\r
416 //\r
417 CurrentBootOptions = EfiBootManagerGetLoadOptions (\r
418 &CurrentBootOptionCount,\r
419 LoadOptionTypeBoot\r
420 );\r
421 //\r
422 // Process the platform boot options.\r
423 //\r
424 for (Index = 0; Index < BootCount; Index++) {\r
425 INTN Match;\r
426 UINTN BootOptionNumber;\r
427\r
428 //\r
429 // If there are any preexistent boot options, and the subject platform boot\r
430 // option is already among them, then don't try to add it. Just get its\r
431 // assigned boot option number so we can associate a hotkey with it. Note\r
432 // that EfiBootManagerFindLoadOption() deals fine with (CurrentBootOptions\r
433 // == NULL) if (CurrentBootCount == 0).\r
434 //\r
435 Match = EfiBootManagerFindLoadOption (\r
436 &BootOptions[Index],\r
437 CurrentBootOptions,\r
438 CurrentBootOptionCount\r
439 );\r
440 if (Match >= 0) {\r
441 BootOptionNumber = CurrentBootOptions[Match].OptionNumber;\r
442 } else {\r
443 //\r
444 // Add the platform boot options as a new one, at the end of the boot\r
445 // order. Note that if the platform provided this boot option with an\r
446 // unassigned option number, then the below function call will assign a\r
447 // number.\r
448 //\r
449 Status = EfiBootManagerAddLoadOptionVariable (\r
450 &BootOptions[Index],\r
451 MAX_UINTN\r
452 );\r
453 if (EFI_ERROR (Status)) {\r
454 DEBUG ((DEBUG_ERROR, "%a: failed to register \"%s\": %r\n",\r
455 __FUNCTION__, BootOptions[Index].Description, Status));\r
456 continue;\r
457 }\r
458 BootOptionNumber = BootOptions[Index].OptionNumber;\r
459 }\r
460\r
461 //\r
462 // Register a hotkey with the boot option, if requested.\r
463 //\r
464 if (BootKeys[Index].UnicodeChar == L'\0') {\r
465 continue;\r
466 }\r
467\r
468 Status = EfiBootManagerAddKeyOptionVariable (\r
469 NULL,\r
470 BootOptionNumber,\r
471 0,\r
2b2959dd 472 &BootKeys[Index],\r
1b6e7633
HZ
473 NULL\r
474 );\r
475 if (EFI_ERROR (Status)) {\r
476 DEBUG ((DEBUG_ERROR, "%a: failed to register hotkey for \"%s\": %r\n",\r
477 __FUNCTION__, BootOptions[Index].Description, Status));\r
478 }\r
479 }\r
480 EfiBootManagerFreeLoadOptions (CurrentBootOptions, CurrentBootOptionCount);\r
481 EfiBootManagerFreeLoadOptions (BootOptions, BootCount);\r
482 FreePool (BootKeys);\r
483}\r
484\r
c976f9cb
AB
485STATIC\r
486VOID\r
487PlatformRegisterOptionsAndKeys (\r
488 VOID\r
489 )\r
490{\r
491 EFI_STATUS Status;\r
492 EFI_INPUT_KEY Enter;\r
493 EFI_INPUT_KEY F2;\r
494 EFI_INPUT_KEY Esc;\r
495 EFI_BOOT_MANAGER_LOAD_OPTION BootOption;\r
496\r
1b6e7633
HZ
497 GetPlatformOptions ();\r
498\r
c976f9cb
AB
499 //\r
500 // Register ENTER as CONTINUE key\r
501 //\r
502 Enter.ScanCode = SCAN_NULL;\r
503 Enter.UnicodeChar = CHAR_CARRIAGE_RETURN;\r
504 Status = EfiBootManagerRegisterContinueKeyOption (0, &Enter, NULL);\r
505 ASSERT_EFI_ERROR (Status);\r
506\r
507 //\r
508 // Map F2 and ESC to Boot Manager Menu\r
509 //\r
510 F2.ScanCode = SCAN_F2;\r
511 F2.UnicodeChar = CHAR_NULL;\r
512 Esc.ScanCode = SCAN_ESC;\r
513 Esc.UnicodeChar = CHAR_NULL;\r
514 Status = EfiBootManagerGetBootManagerMenu (&BootOption);\r
515 ASSERT_EFI_ERROR (Status);\r
516 Status = EfiBootManagerAddKeyOptionVariable (\r
517 NULL, (UINT16) BootOption.OptionNumber, 0, &F2, NULL\r
518 );\r
519 ASSERT (Status == EFI_SUCCESS || Status == EFI_ALREADY_STARTED);\r
520 Status = EfiBootManagerAddKeyOptionVariable (\r
521 NULL, (UINT16) BootOption.OptionNumber, 0, &Esc, NULL\r
522 );\r
523 ASSERT (Status == EFI_SUCCESS || Status == EFI_ALREADY_STARTED);\r
524}\r
525\r
526\r
527//\r
528// BDS Platform Functions\r
529//\r
530/**\r
531 Do the platform init, can be customized by OEM/IBV\r
532 Possible things that can be done in PlatformBootManagerBeforeConsole:\r
533 > Update console variable: 1. include hot-plug devices;\r
534 > 2. Clear ConIn and add SOL for AMT\r
535 > Register new Driver#### or Boot####\r
536 > Register new Key####: e.g.: F12\r
537 > Signal ReadyToLock event\r
538 > Authentication action: 1. connect Auth devices;\r
539 > 2. Identify auto logon user.\r
540**/\r
541VOID\r
542EFIAPI\r
543PlatformBootManagerBeforeConsole (\r
544 VOID\r
545 )\r
546{\r
547 //\r
548 // Signal EndOfDxe PI Event\r
549 //\r
550 EfiEventGroupSignal (&gEfiEndOfDxeEventGroupGuid);\r
551\r
0f9395d7
SM
552 //\r
553 // Dispatch deferred images after EndOfDxe event.\r
554 //\r
555 EfiBootManagerDispatchDeferredImages ();\r
556\r
c976f9cb
AB
557 //\r
558 // Locate the PCI root bridges and make the PCI bus driver connect each,\r
559 // non-recursively. This will produce a number of child handles with PciIo on\r
560 // them.\r
561 //\r
562 FilterAndProcess (&gEfiPciRootBridgeIoProtocolGuid, NULL, Connect);\r
563\r
564 //\r
565 // Find all display class PCI devices (using the handles from the previous\r
566 // step), and connect them non-recursively. This should produce a number of\r
567 // child handles with GOPs on them.\r
568 //\r
569 FilterAndProcess (&gEfiPciIoProtocolGuid, IsPciDisplay, Connect);\r
570\r
571 //\r
572 // Now add the device path of all handles with GOP on them to ConOut and\r
573 // ErrOut.\r
574 //\r
575 FilterAndProcess (&gEfiGraphicsOutputProtocolGuid, NULL, AddOutput);\r
576\r
577 //\r
578 // Add the hardcoded short-form USB keyboard device path to ConIn.\r
579 //\r
580 EfiBootManagerUpdateConsoleVariable (ConIn,\r
581 (EFI_DEVICE_PATH_PROTOCOL *)&mUsbKeyboard, NULL);\r
582\r
583 //\r
584 // Add the hardcoded serial console device path to ConIn, ConOut, ErrOut.\r
585 //\r
b1d3895f
AB
586 STATIC_ASSERT (FixedPcdGet8 (PcdDefaultTerminalType) == 4,\r
587 "PcdDefaultTerminalType must be TTYTERM");\r
7191dd3c
AB
588 STATIC_ASSERT (FixedPcdGet8 (PcdUartDefaultParity) != 0,\r
589 "PcdUartDefaultParity must be set to an actual value, not 'default'");\r
590 STATIC_ASSERT (FixedPcdGet8 (PcdUartDefaultStopBits) != 0,\r
591 "PcdUartDefaultStopBits must be set to an actual value, not 'default'");\r
b1d3895f 592\r
c976f9cb
AB
593 CopyGuid (&mSerialConsole.TermType.Guid, &gEfiTtyTermGuid);\r
594\r
595 EfiBootManagerUpdateConsoleVariable (ConIn,\r
596 (EFI_DEVICE_PATH_PROTOCOL *)&mSerialConsole, NULL);\r
597 EfiBootManagerUpdateConsoleVariable (ConOut,\r
598 (EFI_DEVICE_PATH_PROTOCOL *)&mSerialConsole, NULL);\r
599 EfiBootManagerUpdateConsoleVariable (ErrOut,\r
600 (EFI_DEVICE_PATH_PROTOCOL *)&mSerialConsole, NULL);\r
601\r
602 //\r
603 // Register platform-specific boot options and keyboard shortcuts.\r
604 //\r
605 PlatformRegisterOptionsAndKeys ();\r
606}\r
607\r
cae82316
AB
608STATIC\r
609VOID\r
610HandleCapsules (\r
611 VOID\r
612 )\r
613{\r
614 ESRT_MANAGEMENT_PROTOCOL *EsrtManagement;\r
615 EFI_PEI_HOB_POINTERS HobPointer;\r
616 EFI_CAPSULE_HEADER *CapsuleHeader;\r
617 BOOLEAN NeedReset;\r
618 EFI_STATUS Status;\r
619\r
620 DEBUG ((DEBUG_INFO, "%a: processing capsules ...\n", __FUNCTION__));\r
621\r
622 Status = gBS->LocateProtocol (&gEsrtManagementProtocolGuid, NULL,\r
623 (VOID **)&EsrtManagement);\r
624 if (!EFI_ERROR (Status)) {\r
625 EsrtManagement->SyncEsrtFmp ();\r
626 }\r
627\r
628 //\r
629 // Find all capsule images from hob\r
630 //\r
631 HobPointer.Raw = GetHobList ();\r
632 NeedReset = FALSE;\r
633 while ((HobPointer.Raw = GetNextHob (EFI_HOB_TYPE_UEFI_CAPSULE,\r
634 HobPointer.Raw)) != NULL) {\r
635 CapsuleHeader = (VOID *)(UINTN)HobPointer.Capsule->BaseAddress;\r
636\r
637 Status = ProcessCapsuleImage (CapsuleHeader);\r
638 if (EFI_ERROR (Status)) {\r
639 DEBUG ((DEBUG_ERROR, "%a: failed to process capsule %p - %r\n",\r
640 __FUNCTION__, CapsuleHeader, Status));\r
641 return;\r
642 }\r
643\r
644 NeedReset = TRUE;\r
645 HobPointer.Raw = GET_NEXT_HOB (HobPointer);\r
646 }\r
647\r
648 if (NeedReset) {\r
649 DEBUG ((DEBUG_WARN, "%a: capsule update successful, resetting ...\n",\r
650 __FUNCTION__));\r
651\r
652 gRT->ResetSystem (EfiResetCold, EFI_SUCCESS, 0, NULL);\r
653 CpuDeadLoop();\r
654 }\r
655}\r
656\r
657\r
6c4194c9
AB
658#define VERSION_STRING_PREFIX L"Tianocore/EDK2 firmware version "\r
659\r
c976f9cb
AB
660/**\r
661 Do the platform specific action after the console is ready\r
662 Possible things that can be done in PlatformBootManagerAfterConsole:\r
663 > Console post action:\r
ff5fef14 664 > Dynamically switch output mode from 100x31 to 80x25 for certain scenario\r
c976f9cb
AB
665 > Signal console ready platform customized event\r
666 > Run diagnostics like memory testing\r
667 > Connect certain devices\r
ff5fef14 668 > Dispatch additional option roms\r
c976f9cb
AB
669 > Special boot: e.g.: USB boot, enter UI\r
670**/\r
671VOID\r
672EFIAPI\r
673PlatformBootManagerAfterConsole (\r
674 VOID\r
675 )\r
676{\r
13ca0abb 677 EFI_STATUS Status;\r
6c4194c9
AB
678 EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;\r
679 UINTN FirmwareVerLength;\r
680 UINTN PosX;\r
681 UINTN PosY;\r
682\r
683 FirmwareVerLength = StrLen (PcdGetPtr (PcdFirmwareVersionString));\r
c976f9cb
AB
684\r
685 //\r
686 // Show the splash screen.\r
687 //\r
a43d75e1
AB
688 Status = BootLogoEnableLogo ();\r
689 if (EFI_ERROR (Status)) {\r
6c4194c9 690 if (FirmwareVerLength > 0) {\r
26b99f3b 691 Print (VERSION_STRING_PREFIX L"%s\n",\r
6c4194c9
AB
692 PcdGetPtr (PcdFirmwareVersionString));\r
693 }\r
a43d75e1 694 Print (L"Press ESCAPE for boot options ");\r
6c4194c9
AB
695 } else if (FirmwareVerLength > 0) {\r
696 Status = gBS->HandleProtocol (gST->ConsoleOutHandle,\r
697 &gEfiGraphicsOutputProtocolGuid, (VOID **)&GraphicsOutput);\r
698 if (!EFI_ERROR (Status)) {\r
699 PosX = (GraphicsOutput->Mode->Info->HorizontalResolution -\r
700 (StrLen (VERSION_STRING_PREFIX) + FirmwareVerLength) *\r
701 EFI_GLYPH_WIDTH) / 2;\r
702 PosY = 0;\r
703\r
704 PrintXY (PosX, PosY, NULL, NULL, VERSION_STRING_PREFIX L"%s",\r
705 PcdGetPtr (PcdFirmwareVersionString));\r
706 }\r
a43d75e1 707 }\r
6c4194c9 708\r
c976f9cb
AB
709 //\r
710 // Connect the rest of the devices.\r
711 //\r
712 EfiBootManagerConnectAll ();\r
713\r
cae82316
AB
714 //\r
715 // On ARM, there is currently no reason to use the phased capsule\r
716 // update approach where some capsules are dispatched before EndOfDxe\r
717 // and some are dispatched after. So just handle all capsules here,\r
718 // when the console is up and we can actually give the user some\r
719 // feedback about what is going on.\r
720 //\r
721 HandleCapsules ();\r
4bbcc285 722\r
c976f9cb
AB
723 //\r
724 // Enumerate all possible boot options.\r
725 //\r
726 EfiBootManagerRefreshAllBootOption ();\r
727\r
728 //\r
729 // Register UEFI Shell\r
730 //\r
731 PlatformRegisterFvBootOption (\r
07548e17 732 &gUefiShellFileGuid, L"UEFI Shell", LOAD_OPTION_ACTIVE\r
c976f9cb
AB
733 );\r
734}\r
735\r
736/**\r
737 This function is called each second during the boot manager waits the\r
738 timeout.\r
739\r
740 @param TimeoutRemain The remaining timeout.\r
741**/\r
742VOID\r
743EFIAPI\r
744PlatformBootManagerWaitCallback (\r
745 UINT16 TimeoutRemain\r
746 )\r
747{\r
a43d75e1
AB
748 EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION Black;\r
749 EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION White;\r
750 UINT16 Timeout;\r
751 EFI_STATUS Status;\r
752\r
753 Timeout = PcdGet16 (PcdPlatformBootTimeOut);\r
754\r
755 Black.Raw = 0x00000000;\r
756 White.Raw = 0x00FFFFFF;\r
757\r
758 Status = BootLogoUpdateProgress (\r
759 White.Pixel,\r
760 Black.Pixel,\r
761 L"Press ESCAPE for boot options",\r
762 White.Pixel,\r
763 (Timeout - TimeoutRemain) * 100 / Timeout,\r
764 0\r
765 );\r
766 if (EFI_ERROR (Status)) {\r
767 Print (L".");\r
768 }\r
c976f9cb 769}\r
eea668c9
RN
770\r
771/**\r
772 The function is called when no boot option could be launched,\r
773 including platform recovery options and options pointing to applications\r
774 built into firmware volumes.\r
775\r
776 If this function returns, BDS attempts to enter an infinite loop.\r
777**/\r
778VOID\r
779EFIAPI\r
780PlatformBootManagerUnableToBoot (\r
781 VOID\r
782 )\r
783{\r
784 return;\r
785}\r