]> git.proxmox.com Git - mirror_edk2.git/blame - UefiPayloadPkg/Library/PlatformBootManagerLib/PlatformBootManager.c
UefiPayloadPkg/PlatformBootManagerLib: Correct spacing in boot prompt
[mirror_edk2.git] / UefiPayloadPkg / Library / PlatformBootManagerLib / PlatformBootManager.c
CommitLineData
04af8bf2
DG
1/** @file\r
2 This file include all platform action which can be customized\r
3 by IBV/OEM.\r
4\r
d58016b7 5Copyright (c) 2015 - 2021, Intel Corporation. All rights reserved.<BR>\r
04af8bf2
DG
6SPDX-License-Identifier: BSD-2-Clause-Patent\r
7\r
8**/\r
9\r
10#include "PlatformBootManager.h"\r
11#include "PlatformConsole.h"\r
d58016b7 12#include <Protocol/PlatformBootManagerOverride.h>\r
19a541d7 13#include <Guid/BootManagerMenu.h>\r
14#include <Library/HobLib.h>\r
d58016b7
ZL
15\r
16UNIVERSAL_PAYLOAD_PLATFORM_BOOT_MANAGER_OVERRIDE_PROTOCOL *mUniversalPayloadPlatformBootManagerOverrideInstance = NULL;\r
04af8bf2 17\r
6ef57974
GD
18/**\r
19 Signal EndOfDxe event and install SMM Ready to lock protocol.\r
20\r
21**/\r
04af8bf2
DG
22VOID\r
23InstallReadyToLock (\r
24 VOID\r
25 )\r
26{\r
e5efcf8b
MK
27 EFI_STATUS Status;\r
28 EFI_HANDLE Handle;\r
29 EFI_SMM_ACCESS2_PROTOCOL *SmmAccess;\r
04af8bf2 30\r
e5efcf8b 31 DEBUG ((DEBUG_INFO, "InstallReadyToLock entering......\n"));\r
04af8bf2
DG
32 //\r
33 // Inform the SMM infrastructure that we're entering BDS and may run 3rd party code hereafter\r
34 // Since PI1.2.1, we need signal EndOfDxe as ExitPmAuth\r
35 //\r
36 EfiEventGroupSignal (&gEfiEndOfDxeEventGroupGuid);\r
e5efcf8b 37 DEBUG ((DEBUG_INFO, "All EndOfDxe callbacks have returned successfully\n"));\r
04af8bf2
DG
38\r
39 //\r
40 // Install DxeSmmReadyToLock protocol in order to lock SMM\r
41 //\r
e5efcf8b 42 Status = gBS->LocateProtocol (&gEfiSmmAccess2ProtocolGuid, NULL, (VOID **)&SmmAccess);\r
04af8bf2
DG
43 if (!EFI_ERROR (Status)) {\r
44 Handle = NULL;\r
45 Status = gBS->InstallProtocolInterface (\r
46 &Handle,\r
47 &gEfiDxeSmmReadyToLockProtocolGuid,\r
48 EFI_NATIVE_INTERFACE,\r
49 NULL\r
50 );\r
51 ASSERT_EFI_ERROR (Status);\r
52 }\r
53\r
e5efcf8b 54 DEBUG ((DEBUG_INFO, "InstallReadyToLock end\n"));\r
04af8bf2
DG
55 return;\r
56}\r
57\r
58/**\r
59 Return the index of the load option in the load option array.\r
60\r
61 The function consider two load options are equal when the\r
62 OptionType, Attributes, Description, FilePath and OptionalData are equal.\r
63\r
64 @param Key Pointer to the load option to be found.\r
65 @param Array Pointer to the array of load options to be found.\r
66 @param Count Number of entries in the Array.\r
67\r
68 @retval -1 Key wasn't found in the Array.\r
69 @retval 0 ~ Count-1 The index of the Key in the Array.\r
70**/\r
71INTN\r
72PlatformFindLoadOption (\r
e5efcf8b
MK
73 IN CONST EFI_BOOT_MANAGER_LOAD_OPTION *Key,\r
74 IN CONST EFI_BOOT_MANAGER_LOAD_OPTION *Array,\r
75 IN UINTN Count\r
76 )\r
04af8bf2 77{\r
e5efcf8b 78 UINTN Index;\r
04af8bf2
DG
79\r
80 for (Index = 0; Index < Count; Index++) {\r
81 if ((Key->OptionType == Array[Index].OptionType) &&\r
82 (Key->Attributes == Array[Index].Attributes) &&\r
83 (StrCmp (Key->Description, Array[Index].Description) == 0) &&\r
84 (CompareMem (Key->FilePath, Array[Index].FilePath, GetDevicePathSize (Key->FilePath)) == 0) &&\r
85 (Key->OptionalDataSize == Array[Index].OptionalDataSize) &&\r
e5efcf8b
MK
86 (CompareMem (Key->OptionalData, Array[Index].OptionalData, Key->OptionalDataSize) == 0))\r
87 {\r
88 return (INTN)Index;\r
04af8bf2
DG
89 }\r
90 }\r
91\r
92 return -1;\r
93}\r
94\r
95/**\r
96 Register a boot option using a file GUID in the FV.\r
97\r
98 @param FileGuid The file GUID name in FV.\r
99 @param Description The boot option description.\r
100 @param Attributes The attributes used for the boot option loading.\r
101**/\r
102VOID\r
103PlatformRegisterFvBootOption (\r
e5efcf8b
MK
104 EFI_GUID *FileGuid,\r
105 CHAR16 *Description,\r
106 UINT32 Attributes\r
107 )\r
04af8bf2 108{\r
e5efcf8b
MK
109 EFI_STATUS Status;\r
110 UINTN OptionIndex;\r
111 EFI_BOOT_MANAGER_LOAD_OPTION NewOption;\r
112 EFI_BOOT_MANAGER_LOAD_OPTION *BootOptions;\r
113 UINTN BootOptionCount;\r
114 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH FileNode;\r
115 EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;\r
116 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
117\r
118 Status = gBS->HandleProtocol (gImageHandle, &gEfiLoadedImageProtocolGuid, (VOID **)&LoadedImage);\r
04af8bf2
DG
119 ASSERT_EFI_ERROR (Status);\r
120\r
121 EfiInitializeFwVolDevicepathNode (&FileNode, FileGuid);\r
122 DevicePath = AppendDevicePathNode (\r
123 DevicePathFromHandle (LoadedImage->DeviceHandle),\r
e5efcf8b
MK
124 (EFI_DEVICE_PATH_PROTOCOL *)&FileNode\r
125 );\r
04af8bf2
DG
126\r
127 Status = EfiBootManagerInitializeLoadOption (\r
128 &NewOption,\r
129 LoadOptionNumberUnassigned,\r
130 LoadOptionTypeBoot,\r
131 Attributes,\r
132 Description,\r
133 DevicePath,\r
134 NULL,\r
135 0\r
e5efcf8b 136 );\r
04af8bf2
DG
137 if (!EFI_ERROR (Status)) {\r
138 BootOptions = EfiBootManagerGetLoadOptions (&BootOptionCount, LoadOptionTypeBoot);\r
139\r
140 OptionIndex = PlatformFindLoadOption (&NewOption, BootOptions, BootOptionCount);\r
141\r
142 if (OptionIndex == -1) {\r
e5efcf8b 143 Status = EfiBootManagerAddLoadOptionVariable (&NewOption, (UINTN)-1);\r
04af8bf2
DG
144 ASSERT_EFI_ERROR (Status);\r
145 }\r
e5efcf8b 146\r
04af8bf2
DG
147 EfiBootManagerFreeLoadOption (&NewOption);\r
148 EfiBootManagerFreeLoadOptions (BootOptions, BootOptionCount);\r
149 }\r
150}\r
151\r
152/**\r
153 Do the platform specific action before the console is connected.\r
154\r
155 Such as:\r
156 Update console variable;\r
157 Register new Driver#### or Boot####;\r
158 Signal ReadyToLock event.\r
159**/\r
160VOID\r
161EFIAPI\r
162PlatformBootManagerBeforeConsole (\r
163 VOID\r
e5efcf8b 164 )\r
04af8bf2 165{\r
e5efcf8b 166 EFI_INPUT_KEY Enter;\r
af74efe4 167 EFI_INPUT_KEY CustomKey;\r
e5efcf8b
MK
168 EFI_INPUT_KEY Down;\r
169 EFI_BOOT_MANAGER_LOAD_OPTION BootOption;\r
170 EFI_STATUS Status;\r
d58016b7 171\r
e5efcf8b 172 Status = gBS->LocateProtocol (&gUniversalPayloadPlatformBootManagerOverrideProtocolGuid, NULL, (VOID **)&mUniversalPayloadPlatformBootManagerOverrideInstance);\r
d58016b7
ZL
173 if (EFI_ERROR (Status)) {\r
174 mUniversalPayloadPlatformBootManagerOverrideInstance = NULL;\r
175 }\r
e5efcf8b
MK
176\r
177 if (mUniversalPayloadPlatformBootManagerOverrideInstance != NULL) {\r
178 mUniversalPayloadPlatformBootManagerOverrideInstance->BeforeConsole ();\r
d58016b7
ZL
179 return;\r
180 }\r
04af8bf2 181\r
04af8bf2
DG
182 //\r
183 // Register ENTER as CONTINUE key\r
184 //\r
185 Enter.ScanCode = SCAN_NULL;\r
186 Enter.UnicodeChar = CHAR_CARRIAGE_RETURN;\r
187 EfiBootManagerRegisterContinueKeyOption (0, &Enter, NULL);\r
188\r
af74efe4
SR
189 if (FixedPcdGetBool (PcdBootManagerEscape)) {\r
190 //\r
191 // Map Esc to Boot Manager Menu\r
192 //\r
193 CustomKey.ScanCode = SCAN_ESC;\r
194 CustomKey.UnicodeChar = CHAR_NULL;\r
195 } else {\r
196 //\r
197 // Map Esc to Boot Manager Menu\r
198 //\r
199 CustomKey.ScanCode = SCAN_F2;\r
200 CustomKey.UnicodeChar = CHAR_NULL;\r
201 }\r
202\r
04af8bf2 203 EfiBootManagerGetBootManagerMenu (&BootOption);\r
af74efe4 204 EfiBootManagerAddKeyOptionVariable (NULL, (UINT16)BootOption.OptionNumber, 0, &CustomKey, NULL);\r
04af8bf2
DG
205\r
206 //\r
207 // Also add Down key to Boot Manager Menu since some serial terminals don't support F2 key.\r
208 //\r
209 Down.ScanCode = SCAN_DOWN;\r
210 Down.UnicodeChar = CHAR_NULL;\r
211 EfiBootManagerGetBootManagerMenu (&BootOption);\r
e5efcf8b 212 EfiBootManagerAddKeyOptionVariable (NULL, (UINT16)BootOption.OptionNumber, 0, &Down, NULL);\r
04af8bf2
DG
213\r
214 //\r
215 // Install ready to lock.\r
216 // This needs to be done before option rom dispatched.\r
217 //\r
218 InstallReadyToLock ();\r
219\r
220 //\r
221 // Dispatch deferred images after EndOfDxe event and ReadyToLock installation.\r
222 //\r
223 EfiBootManagerDispatchDeferredImages ();\r
2e1e8c35
GD
224\r
225 PlatformConsoleInit ();\r
04af8bf2
DG
226}\r
227\r
228/**\r
229 Do the platform specific action after the console is connected.\r
230\r
231 Such as:\r
232 Dynamically switch output mode;\r
233 Signal console ready platform customized event;\r
234 Run diagnostics like memory testing;\r
235 Connect certain devices;\r
236 Dispatch additional option roms.\r
237**/\r
238VOID\r
239EFIAPI\r
240PlatformBootManagerAfterConsole (\r
241 VOID\r
e5efcf8b 242 )\r
04af8bf2
DG
243{\r
244 EFI_GRAPHICS_OUTPUT_BLT_PIXEL Black;\r
245 EFI_GRAPHICS_OUTPUT_BLT_PIXEL White;\r
246\r
e5efcf8b
MK
247 if (mUniversalPayloadPlatformBootManagerOverrideInstance != NULL) {\r
248 mUniversalPayloadPlatformBootManagerOverrideInstance->AfterConsole ();\r
d58016b7
ZL
249 return;\r
250 }\r
e5efcf8b 251\r
04af8bf2
DG
252 Black.Blue = Black.Green = Black.Red = Black.Reserved = 0;\r
253 White.Blue = White.Green = White.Red = White.Reserved = 0xFF;\r
254\r
255 EfiBootManagerConnectAll ();\r
256 EfiBootManagerRefreshAllBootOption ();\r
257\r
258 //\r
259 // Register UEFI Shell\r
260 //\r
261 PlatformRegisterFvBootOption (PcdGetPtr (PcdShellFile), L"UEFI Shell", LOAD_OPTION_ACTIVE);\r
262\r
af74efe4
SR
263 if (FixedPcdGetBool (PcdBootManagerEscape)) {\r
264 Print (\r
265 L"\n"\r
07c8e5e5 266 L" Esc or Down to enter Boot Manager Menu.\n"\r
d2191197 267 L" ENTER to boot directly.\n"\r
af74efe4
SR
268 L"\n"\r
269 );\r
270 } else {\r
271 Print (\r
272 L"\n"\r
07c8e5e5
SR
273 L" F2 or Down to enter Boot Manager Menu.\n"\r
274 L" ENTER to boot directly.\n"\r
af74efe4
SR
275 L"\n"\r
276 );\r
277 }\r
04af8bf2
DG
278}\r
279\r
280/**\r
281 This function is called each second during the boot manager waits the timeout.\r
282\r
283 @param TimeoutRemain The remaining timeout.\r
284**/\r
285VOID\r
286EFIAPI\r
287PlatformBootManagerWaitCallback (\r
e5efcf8b
MK
288 UINT16 TimeoutRemain\r
289 )\r
04af8bf2 290{\r
e5efcf8b 291 if (mUniversalPayloadPlatformBootManagerOverrideInstance != NULL) {\r
d58016b7
ZL
292 mUniversalPayloadPlatformBootManagerOverrideInstance->WaitCallback (TimeoutRemain);\r
293 }\r
e5efcf8b 294\r
04af8bf2
DG
295 return;\r
296}\r
297\r
298/**\r
299 The function is called when no boot option could be launched,\r
300 including platform recovery options and options pointing to applications\r
301 built into firmware volumes.\r
302\r
303 If this function returns, BDS attempts to enter an infinite loop.\r
304**/\r
305VOID\r
306EFIAPI\r
307PlatformBootManagerUnableToBoot (\r
308 VOID\r
309 )\r
310{\r
e5efcf8b
MK
311 if (mUniversalPayloadPlatformBootManagerOverrideInstance != NULL) {\r
312 mUniversalPayloadPlatformBootManagerOverrideInstance->UnableToBoot ();\r
d58016b7 313 }\r
e5efcf8b 314\r
04af8bf2
DG
315 return;\r
316}\r
317\r
19a541d7 318/**\r
319 Get/update PcdBootManagerMenuFile from GUID HOB which will be assigned in bootloader.\r
320\r
321 @param ImageHandle The firmware allocated handle for the EFI image.\r
322 @param SystemTable A pointer to the EFI System Table.\r
323\r
324 @retval EFI_SUCCESS The entry point is executed successfully.\r
325 @retval other Some error occurs.\r
326\r
327**/\r
328EFI_STATUS\r
329EFIAPI\r
330PlatformBootManagerLibConstructor (\r
331 IN EFI_HANDLE ImageHandle,\r
332 IN EFI_SYSTEM_TABLE *SystemTable\r
e5efcf8b 333 )\r
19a541d7 334{\r
335 EFI_STATUS Status;\r
336 UINTN Size;\r
337 VOID *GuidHob;\r
338 UNIVERSAL_PAYLOAD_GENERIC_HEADER *GenericHeader;\r
339 UNIVERSAL_PAYLOAD_BOOT_MANAGER_MENU *BootManagerMenuFile;\r
340\r
341 GuidHob = GetFirstGuidHob (&gEdkiiBootManagerMenuFileGuid);\r
342\r
343 if (GuidHob == NULL) {\r
344 //\r
345 // If the HOB is not create, the default value of PcdBootManagerMenuFile will be used.\r
346 //\r
347 return EFI_SUCCESS;\r
348 }\r
349\r
e5efcf8b 350 GenericHeader = (UNIVERSAL_PAYLOAD_GENERIC_HEADER *)GET_GUID_HOB_DATA (GuidHob);\r
19a541d7 351 if ((sizeof (UNIVERSAL_PAYLOAD_GENERIC_HEADER) > GET_GUID_HOB_DATA_SIZE (GuidHob)) || (GenericHeader->Length > GET_GUID_HOB_DATA_SIZE (GuidHob))) {\r
352 return EFI_NOT_FOUND;\r
353 }\r
e5efcf8b 354\r
19a541d7 355 if (GenericHeader->Revision == UNIVERSAL_PAYLOAD_BOOT_MANAGER_MENU_REVISION) {\r
e5efcf8b 356 BootManagerMenuFile = (UNIVERSAL_PAYLOAD_BOOT_MANAGER_MENU *)GET_GUID_HOB_DATA (GuidHob);\r
19a541d7 357 if (BootManagerMenuFile->Header.Length < UNIVERSAL_PAYLOAD_SIZEOF_THROUGH_FIELD (UNIVERSAL_PAYLOAD_BOOT_MANAGER_MENU, FileName)) {\r
358 return EFI_NOT_FOUND;\r
359 }\r
e5efcf8b
MK
360\r
361 Size = sizeof (BootManagerMenuFile->FileName);\r
19a541d7 362 Status = PcdSetPtrS (PcdBootManagerMenuFile, &Size, &BootManagerMenuFile->FileName);\r
363 ASSERT_EFI_ERROR (Status);\r
364 } else {\r
365 return EFI_NOT_FOUND;\r
366 }\r
367\r
368 return EFI_SUCCESS;\r
369}\r