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