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