]> git.proxmox.com Git - mirror_edk2.git/blame - UefiPayloadPkg/Library/PlatformBootManagerLib/PlatformBootManager.c
UefiPayloadPkg: Get platform specific logic via protocol for BDS
[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
ZL
12#include <Protocol/PlatformBootManagerOverride.h>\r
13\r
14UNIVERSAL_PAYLOAD_PLATFORM_BOOT_MANAGER_OVERRIDE_PROTOCOL *mUniversalPayloadPlatformBootManagerOverrideInstance = NULL;\r
04af8bf2
DG
15\r
16VOID\r
17InstallReadyToLock (\r
18 VOID\r
19 )\r
20{\r
21 EFI_STATUS Status;\r
22 EFI_HANDLE Handle;\r
23 EFI_SMM_ACCESS2_PROTOCOL *SmmAccess;\r
24\r
25 DEBUG((DEBUG_INFO,"InstallReadyToLock entering......\n"));\r
26 //\r
27 // Inform the SMM infrastructure that we're entering BDS and may run 3rd party code hereafter\r
28 // Since PI1.2.1, we need signal EndOfDxe as ExitPmAuth\r
29 //\r
30 EfiEventGroupSignal (&gEfiEndOfDxeEventGroupGuid);\r
31 DEBUG((DEBUG_INFO,"All EndOfDxe callbacks have returned successfully\n"));\r
32\r
33 //\r
34 // Install DxeSmmReadyToLock protocol in order to lock SMM\r
35 //\r
36 Status = gBS->LocateProtocol (&gEfiSmmAccess2ProtocolGuid, NULL, (VOID **) &SmmAccess);\r
37 if (!EFI_ERROR (Status)) {\r
38 Handle = NULL;\r
39 Status = gBS->InstallProtocolInterface (\r
40 &Handle,\r
41 &gEfiDxeSmmReadyToLockProtocolGuid,\r
42 EFI_NATIVE_INTERFACE,\r
43 NULL\r
44 );\r
45 ASSERT_EFI_ERROR (Status);\r
46 }\r
47\r
48 DEBUG((DEBUG_INFO,"InstallReadyToLock end\n"));\r
49 return;\r
50}\r
51\r
52/**\r
53 Return the index of the load option in the load option array.\r
54\r
55 The function consider two load options are equal when the\r
56 OptionType, Attributes, Description, FilePath and OptionalData are equal.\r
57\r
58 @param Key Pointer to the load option to be found.\r
59 @param Array Pointer to the array of load options to be found.\r
60 @param Count Number of entries in the Array.\r
61\r
62 @retval -1 Key wasn't found in the Array.\r
63 @retval 0 ~ Count-1 The index of the Key in the Array.\r
64**/\r
65INTN\r
66PlatformFindLoadOption (\r
67 IN CONST EFI_BOOT_MANAGER_LOAD_OPTION *Key,\r
68 IN CONST EFI_BOOT_MANAGER_LOAD_OPTION *Array,\r
69 IN UINTN Count\r
70)\r
71{\r
72 UINTN Index;\r
73\r
74 for (Index = 0; Index < Count; Index++) {\r
75 if ((Key->OptionType == Array[Index].OptionType) &&\r
76 (Key->Attributes == Array[Index].Attributes) &&\r
77 (StrCmp (Key->Description, Array[Index].Description) == 0) &&\r
78 (CompareMem (Key->FilePath, Array[Index].FilePath, GetDevicePathSize (Key->FilePath)) == 0) &&\r
79 (Key->OptionalDataSize == Array[Index].OptionalDataSize) &&\r
80 (CompareMem (Key->OptionalData, Array[Index].OptionalData, Key->OptionalDataSize) == 0)) {\r
81 return (INTN) Index;\r
82 }\r
83 }\r
84\r
85 return -1;\r
86}\r
87\r
88/**\r
89 Register a boot option using a file GUID in the FV.\r
90\r
91 @param FileGuid The file GUID name in FV.\r
92 @param Description The boot option description.\r
93 @param Attributes The attributes used for the boot option loading.\r
94**/\r
95VOID\r
96PlatformRegisterFvBootOption (\r
97 EFI_GUID *FileGuid,\r
98 CHAR16 *Description,\r
99 UINT32 Attributes\r
100)\r
101{\r
102 EFI_STATUS Status;\r
103 UINTN OptionIndex;\r
104 EFI_BOOT_MANAGER_LOAD_OPTION NewOption;\r
105 EFI_BOOT_MANAGER_LOAD_OPTION *BootOptions;\r
106 UINTN BootOptionCount;\r
107 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH FileNode;\r
108 EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;\r
109 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
110\r
111 Status = gBS->HandleProtocol (gImageHandle, &gEfiLoadedImageProtocolGuid, (VOID **) &LoadedImage);\r
112 ASSERT_EFI_ERROR (Status);\r
113\r
114 EfiInitializeFwVolDevicepathNode (&FileNode, FileGuid);\r
115 DevicePath = AppendDevicePathNode (\r
116 DevicePathFromHandle (LoadedImage->DeviceHandle),\r
117 (EFI_DEVICE_PATH_PROTOCOL *) &FileNode\r
118 );\r
119\r
120 Status = EfiBootManagerInitializeLoadOption (\r
121 &NewOption,\r
122 LoadOptionNumberUnassigned,\r
123 LoadOptionTypeBoot,\r
124 Attributes,\r
125 Description,\r
126 DevicePath,\r
127 NULL,\r
128 0\r
129 );\r
130 if (!EFI_ERROR (Status)) {\r
131 BootOptions = EfiBootManagerGetLoadOptions (&BootOptionCount, LoadOptionTypeBoot);\r
132\r
133 OptionIndex = PlatformFindLoadOption (&NewOption, BootOptions, BootOptionCount);\r
134\r
135 if (OptionIndex == -1) {\r
136 Status = EfiBootManagerAddLoadOptionVariable (&NewOption, (UINTN) -1);\r
137 ASSERT_EFI_ERROR (Status);\r
138 }\r
139 EfiBootManagerFreeLoadOption (&NewOption);\r
140 EfiBootManagerFreeLoadOptions (BootOptions, BootOptionCount);\r
141 }\r
142}\r
143\r
144/**\r
145 Do the platform specific action before the console is connected.\r
146\r
147 Such as:\r
148 Update console variable;\r
149 Register new Driver#### or Boot####;\r
150 Signal ReadyToLock event.\r
151**/\r
152VOID\r
153EFIAPI\r
154PlatformBootManagerBeforeConsole (\r
155 VOID\r
156)\r
157{\r
158 EFI_INPUT_KEY Enter;\r
159 EFI_INPUT_KEY F2;\r
160 EFI_INPUT_KEY Down;\r
161 EFI_BOOT_MANAGER_LOAD_OPTION BootOption;\r
d58016b7
ZL
162 EFI_STATUS Status;\r
163\r
164 Status = gBS->LocateProtocol (&gUniversalPayloadPlatformBootManagerOverrideProtocolGuid, NULL, (VOID **) &mUniversalPayloadPlatformBootManagerOverrideInstance);\r
165 if (EFI_ERROR (Status)) {\r
166 mUniversalPayloadPlatformBootManagerOverrideInstance = NULL;\r
167 }\r
168 if (mUniversalPayloadPlatformBootManagerOverrideInstance != NULL){\r
169 mUniversalPayloadPlatformBootManagerOverrideInstance->BeforeConsole();\r
170 return;\r
171 }\r
04af8bf2 172\r
04af8bf2
DG
173 //\r
174 // Register ENTER as CONTINUE key\r
175 //\r
176 Enter.ScanCode = SCAN_NULL;\r
177 Enter.UnicodeChar = CHAR_CARRIAGE_RETURN;\r
178 EfiBootManagerRegisterContinueKeyOption (0, &Enter, NULL);\r
179\r
180 //\r
181 // Map F2 to Boot Manager Menu\r
182 //\r
183 F2.ScanCode = SCAN_F2;\r
184 F2.UnicodeChar = CHAR_NULL;\r
185 EfiBootManagerGetBootManagerMenu (&BootOption);\r
186 EfiBootManagerAddKeyOptionVariable (NULL, (UINT16) BootOption.OptionNumber, 0, &F2, NULL);\r
187\r
188 //\r
189 // Also add Down key to Boot Manager Menu since some serial terminals don't support F2 key.\r
190 //\r
191 Down.ScanCode = SCAN_DOWN;\r
192 Down.UnicodeChar = CHAR_NULL;\r
193 EfiBootManagerGetBootManagerMenu (&BootOption);\r
194 EfiBootManagerAddKeyOptionVariable (NULL, (UINT16) BootOption.OptionNumber, 0, &Down, NULL);\r
195\r
196 //\r
197 // Install ready to lock.\r
198 // This needs to be done before option rom dispatched.\r
199 //\r
200 InstallReadyToLock ();\r
201\r
202 //\r
203 // Dispatch deferred images after EndOfDxe event and ReadyToLock installation.\r
204 //\r
205 EfiBootManagerDispatchDeferredImages ();\r
2e1e8c35
GD
206\r
207 PlatformConsoleInit ();\r
04af8bf2
DG
208}\r
209\r
210/**\r
211 Do the platform specific action after the console is connected.\r
212\r
213 Such as:\r
214 Dynamically switch output mode;\r
215 Signal console ready platform customized event;\r
216 Run diagnostics like memory testing;\r
217 Connect certain devices;\r
218 Dispatch additional option roms.\r
219**/\r
220VOID\r
221EFIAPI\r
222PlatformBootManagerAfterConsole (\r
223 VOID\r
224)\r
225{\r
226 EFI_GRAPHICS_OUTPUT_BLT_PIXEL Black;\r
227 EFI_GRAPHICS_OUTPUT_BLT_PIXEL White;\r
228\r
d58016b7
ZL
229 if (mUniversalPayloadPlatformBootManagerOverrideInstance != NULL){\r
230 mUniversalPayloadPlatformBootManagerOverrideInstance->AfterConsole();\r
231 return;\r
232 }\r
04af8bf2
DG
233 Black.Blue = Black.Green = Black.Red = Black.Reserved = 0;\r
234 White.Blue = White.Green = White.Red = White.Reserved = 0xFF;\r
235\r
236 EfiBootManagerConnectAll ();\r
237 EfiBootManagerRefreshAllBootOption ();\r
238\r
239 //\r
240 // Register UEFI Shell\r
241 //\r
242 PlatformRegisterFvBootOption (PcdGetPtr (PcdShellFile), L"UEFI Shell", LOAD_OPTION_ACTIVE);\r
243\r
244 Print (\r
245 L"\n"\r
246 L"F2 or Down to enter Boot Manager Menu.\n"\r
247 L"ENTER to boot directly.\n"\r
248 L"\n"\r
249 );\r
250\r
251}\r
252\r
253/**\r
254 This function is called each second during the boot manager waits the timeout.\r
255\r
256 @param TimeoutRemain The remaining timeout.\r
257**/\r
258VOID\r
259EFIAPI\r
260PlatformBootManagerWaitCallback (\r
261 UINT16 TimeoutRemain\r
262)\r
263{\r
d58016b7
ZL
264 if (mUniversalPayloadPlatformBootManagerOverrideInstance != NULL){\r
265 mUniversalPayloadPlatformBootManagerOverrideInstance->WaitCallback (TimeoutRemain);\r
266 }\r
04af8bf2
DG
267 return;\r
268}\r
269\r
270/**\r
271 The function is called when no boot option could be launched,\r
272 including platform recovery options and options pointing to applications\r
273 built into firmware volumes.\r
274\r
275 If this function returns, BDS attempts to enter an infinite loop.\r
276**/\r
277VOID\r
278EFIAPI\r
279PlatformBootManagerUnableToBoot (\r
280 VOID\r
281 )\r
282{\r
d58016b7
ZL
283 if (mUniversalPayloadPlatformBootManagerOverrideInstance != NULL){\r
284 mUniversalPayloadPlatformBootManagerOverrideInstance->UnableToBoot();\r
285 }\r
04af8bf2
DG
286 return;\r
287}\r
288\r