]> git.proxmox.com Git - mirror_edk2.git/blame - IntelFrameworkModulePkg/Universal/BdsDxe/BootMngr/BootManager.c
IntelFrameworkModulePkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / IntelFrameworkModulePkg / Universal / BdsDxe / BootMngr / BootManager.c
CommitLineData
5c08e117 1/** @file\r
2 The platform boot manager reference implementation\r
3\r
0a6f4824 4Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>\r
c0a00b14 5SPDX-License-Identifier: BSD-2-Clause-Patent\r
5c08e117 6\r
7**/\r
8\r
9#include "BootManager.h"\r
10\r
11UINT16 mKeyInput;\r
ce5fad41 12LIST_ENTRY mBootOptionsList;\r
5c08e117 13BDS_COMMON_OPTION *gOption;\r
22d1f978
RN
14CHAR16 *mDeviceTypeStr[] = {\r
15 L"Legacy BEV",\r
16 L"Legacy Floppy",\r
17 L"Legacy Hard Drive",\r
18 L"Legacy CD ROM",\r
19 L"Legacy PCMCIA",\r
20 L"Legacy USB",\r
21 L"Legacy Embedded Network",\r
22 L"Legacy Unknown Device"\r
23};\r
24\r
5c08e117 25\r
f6f910dd 26HII_VENDOR_DEVICE_PATH mBootManagerHiiVendorDevicePath = {\r
27 {\r
28 {\r
29 HARDWARE_DEVICE_PATH,\r
30 HW_VENDOR_DP,\r
31 {\r
32 (UINT8) (sizeof (VENDOR_DEVICE_PATH)),\r
33 (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8)\r
34 }\r
35 },\r
e24fc103 36 BOOT_MANAGER_FORMSET_GUID\r
f6f910dd 37 },\r
38 {\r
39 END_DEVICE_PATH_TYPE,\r
40 END_ENTIRE_DEVICE_PATH_SUBTYPE,\r
0a6f4824 41 {\r
f6f910dd 42 (UINT8) (END_DEVICE_PATH_LENGTH),\r
43 (UINT8) ((END_DEVICE_PATH_LENGTH) >> 8)\r
44 }\r
45 }\r
46};\r
47\r
5c08e117 48BOOT_MANAGER_CALLBACK_DATA gBootManagerPrivate = {\r
49 BOOT_MANAGER_CALLBACK_DATA_SIGNATURE,\r
50 NULL,\r
51 NULL,\r
52 {\r
53 FakeExtractConfig,\r
54 FakeRouteConfig,\r
55 BootManagerCallback\r
56 }\r
57};\r
58\r
59/**\r
baf46e70 60 This call back function is registered with Boot Manager formset.\r
5c08e117 61 When user selects a boot option, this call back function will\r
62 be triggered. The boot option is saved for later processing.\r
63\r
64\r
65 @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
66 @param Action Specifies the type of action taken by the browser.\r
67 @param QuestionId A unique value which is sent to the original exporting driver\r
68 so that it can identify the type of data to expect.\r
69 @param Type The type of value for the question.\r
70 @param Value A pointer to the data being sent to the original exporting driver.\r
71 @param ActionRequest On return, points to the action requested by the callback function.\r
72\r
73 @retval EFI_SUCCESS The callback successfully handled the action.\r
74 @retval EFI_INVALID_PARAMETER The setup browser call this function with invalid parameters.\r
75\r
76**/\r
77EFI_STATUS\r
78EFIAPI\r
79BootManagerCallback (\r
80 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,\r
81 IN EFI_BROWSER_ACTION Action,\r
82 IN EFI_QUESTION_ID QuestionId,\r
83 IN UINT8 Type,\r
84 IN EFI_IFR_TYPE_VALUE *Value,\r
85 OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest\r
86 )\r
87{\r
88 BDS_COMMON_OPTION *Option;\r
89 LIST_ENTRY *Link;\r
90 UINT16 KeyCount;\r
91\r
84724077 92 if (Action == EFI_BROWSER_ACTION_CHANGED) {\r
d88f86f1
ED
93 if ((Value == NULL) || (ActionRequest == NULL)) {\r
94 return EFI_INVALID_PARAMETER;\r
95 }\r
96\r
4548fc2a 97 //\r
d88f86f1 98 // Initialize the key count\r
4548fc2a 99 //\r
d88f86f1 100 KeyCount = 0;\r
5c08e117 101\r
d88f86f1
ED
102 for (Link = GetFirstNode (&mBootOptionsList); !IsNull (&mBootOptionsList, Link); Link = GetNextNode (&mBootOptionsList, Link)) {\r
103 Option = CR (Link, BDS_COMMON_OPTION, Link, BDS_LOAD_OPTION_SIGNATURE);\r
5c08e117 104\r
d88f86f1 105 KeyCount++;\r
5c08e117 106\r
d88f86f1 107 gOption = Option;\r
5c08e117 108\r
5c08e117 109 //\r
d88f86f1 110 // Is this device the one chosen?\r
5c08e117 111 //\r
d88f86f1
ED
112 if (KeyCount == QuestionId) {\r
113 //\r
114 // Assigning the returned Key to a global allows the original routine to know what was chosen\r
115 //\r
116 mKeyInput = QuestionId;\r
117\r
118 //\r
119 // Request to exit SendForm(), so that we could boot the selected option\r
120 //\r
121 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT;\r
122 break;\r
123 }\r
5c08e117 124 }\r
d88f86f1
ED
125\r
126 return EFI_SUCCESS;\r
5c08e117 127 }\r
128\r
d88f86f1
ED
129 //\r
130 // All other action return unsupported.\r
131 //\r
132 return EFI_UNSUPPORTED;\r
5c08e117 133}\r
134\r
135/**\r
136\r
137 Registers HII packages for the Boot Manger to HII Database.\r
138 It also registers the browser call back function.\r
139\r
cb7d01c0 140 @retval EFI_SUCCESS HII packages for the Boot Manager were registered successfully.\r
141 @retval EFI_OUT_OF_RESOURCES HII packages for the Boot Manager failed to be registered.\r
5c08e117 142\r
143**/\r
144EFI_STATUS\r
145InitializeBootManager (\r
146 VOID\r
147 )\r
148{\r
149 EFI_STATUS Status;\r
5c08e117 150\r
151 //\r
f6f910dd 152 // Install Device Path Protocol and Config Access protocol to driver handle\r
5c08e117 153 //\r
f6f910dd 154 Status = gBS->InstallMultipleProtocolInterfaces (\r
5c08e117 155 &gBootManagerPrivate.DriverHandle,\r
f6f910dd 156 &gEfiDevicePathProtocolGuid,\r
157 &mBootManagerHiiVendorDevicePath,\r
5c08e117 158 &gEfiHiiConfigAccessProtocolGuid,\r
f6f910dd 159 &gBootManagerPrivate.ConfigAccess,\r
160 NULL\r
5c08e117 161 );\r
162 ASSERT_EFI_ERROR (Status);\r
163\r
164 //\r
165 // Publish our HII data\r
166 //\r
cb7d01c0 167 gBootManagerPrivate.HiiHandle = HiiAddPackages (\r
e24fc103 168 &gBootManagerFormSetGuid,\r
cb7d01c0 169 gBootManagerPrivate.DriverHandle,\r
170 BootManagerVfrBin,\r
171 BdsDxeStrings,\r
172 NULL\r
173 );\r
174 if (gBootManagerPrivate.HiiHandle == NULL) {\r
175 Status = EFI_OUT_OF_RESOURCES;\r
176 } else {\r
177 Status = EFI_SUCCESS;\r
178 }\r
5c08e117 179 return Status;\r
180}\r
181\r
182/**\r
baf46e70 183 This function invokes Boot Manager. If all devices have not a chance to be connected,\r
0a6f4824 184 the connect all will be triggered. It then enumerate all boot options. If\r
5c08e117 185 a boot option from the Boot Manager page is selected, Boot Manager will boot\r
186 from this boot option.\r
0a6f4824 187\r
5c08e117 188**/\r
189VOID\r
190CallBootManager (\r
191 VOID\r
192 )\r
193{\r
194 EFI_STATUS Status;\r
195 BDS_COMMON_OPTION *Option;\r
196 LIST_ENTRY *Link;\r
5c08e117 197 CHAR16 *ExitData;\r
198 UINTN ExitDataSize;\r
199 EFI_STRING_ID Token;\r
200 EFI_INPUT_KEY Key;\r
5c08e117 201 CHAR16 *HelpString;\r
44cbebec 202 UINTN HelpSize;\r
5c08e117 203 EFI_STRING_ID HelpToken;\r
204 UINT16 *TempStr;\r
205 EFI_HII_HANDLE HiiHandle;\r
206 EFI_BROWSER_ACTION_REQUEST ActionRequest;\r
75bf9d0e
LG
207 VOID *StartOpCodeHandle;\r
208 VOID *EndOpCodeHandle;\r
209 EFI_IFR_GUID_LABEL *StartLabel;\r
210 EFI_IFR_GUID_LABEL *EndLabel;\r
22d1f978
RN
211 UINT16 DeviceType;\r
212 BOOLEAN IsLegacyOption;\r
213 BOOLEAN NeedEndOp;\r
5c08e117 214\r
22d1f978
RN
215 DeviceType = (UINT16) -1;\r
216 gOption = NULL;\r
ce5fad41 217 InitializeListHead (&mBootOptionsList);\r
5c08e117 218\r
219 //\r
220 // Connect all prior to entering the platform setup menu.\r
221 //\r
222 if (!gConnectAllHappened) {\r
223 BdsLibConnectAllDriversToAllControllers ();\r
224 gConnectAllHappened = TRUE;\r
225 }\r
5c08e117 226\r
ce5fad41 227 BdsLibEnumerateAllBootOption (&mBootOptionsList);\r
5c08e117 228\r
16e5944a
RN
229 //\r
230 // Group the legacy boot options for the same device type\r
231 //\r
232 GroupMultipleLegacyBootOption4SameType ();\r
233\r
234 InitializeListHead (&mBootOptionsList);\r
235 BdsLibBuildOptionFromVar (&mBootOptionsList, L"BootOrder");\r
236\r
5c08e117 237 HiiHandle = gBootManagerPrivate.HiiHandle;\r
238\r
239 //\r
240 // Allocate space for creation of UpdateData Buffer\r
241 //\r
75bf9d0e
LG
242 StartOpCodeHandle = HiiAllocateOpCodeHandle ();\r
243 ASSERT (StartOpCodeHandle != NULL);\r
244\r
245 EndOpCodeHandle = HiiAllocateOpCodeHandle ();\r
246 ASSERT (EndOpCodeHandle != NULL);\r
247\r
248 //\r
249 // Create Hii Extend Label OpCode as the start opcode\r
250 //\r
251 StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (StartOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));\r
252 StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;\r
253 StartLabel->Number = LABEL_BOOT_OPTION;\r
254\r
255 //\r
256 // Create Hii Extend Label OpCode as the end opcode\r
257 //\r
258 EndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (EndOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));\r
259 EndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;\r
260 EndLabel->Number = LABEL_BOOT_OPTION_END;\r
5c08e117 261\r
262 mKeyInput = 0;\r
22d1f978 263 NeedEndOp = FALSE;\r
ce5fad41 264 for (Link = GetFirstNode (&mBootOptionsList); !IsNull (&mBootOptionsList, Link); Link = GetNextNode (&mBootOptionsList, Link)) {\r
5c08e117 265 Option = CR (Link, BDS_COMMON_OPTION, Link, BDS_LOAD_OPTION_SIGNATURE);\r
266\r
267 //\r
268 // At this stage we are creating a menu entry, thus the Keys are reproduceable\r
269 //\r
270 mKeyInput++;\r
271\r
272 //\r
16e5944a 273 // Don't display the hidden/inactive boot option\r
5c08e117 274 //\r
16e5944a 275 if (((Option->Attribute & LOAD_OPTION_HIDDEN) != 0) || ((Option->Attribute & LOAD_OPTION_ACTIVE) == 0)) {\r
5c08e117 276 continue;\r
277 }\r
22d1f978
RN
278\r
279 //\r
280 // Group the legacy boot option in the sub title created dynamically\r
281 //\r
282 IsLegacyOption = (BOOLEAN) (\r
283 (DevicePathType (Option->DevicePath) == BBS_DEVICE_PATH) &&\r
284 (DevicePathSubType (Option->DevicePath) == BBS_BBS_DP)\r
285 );\r
286\r
287 if (!IsLegacyOption && NeedEndOp) {\r
288 NeedEndOp = FALSE;\r
289 HiiCreateEndOpCode (StartOpCodeHandle);\r
290 }\r
0a6f4824 291\r
22d1f978
RN
292 if (IsLegacyOption && DeviceType != ((BBS_BBS_DEVICE_PATH *) Option->DevicePath)->DeviceType) {\r
293 if (NeedEndOp) {\r
294 HiiCreateEndOpCode (StartOpCodeHandle);\r
295 }\r
296\r
297 DeviceType = ((BBS_BBS_DEVICE_PATH *) Option->DevicePath)->DeviceType;\r
298 Token = HiiSetString (\r
299 HiiHandle,\r
300 0,\r
301 mDeviceTypeStr[\r
bdb898a5 302 MIN (DeviceType & 0xF, ARRAY_SIZE (mDeviceTypeStr) - 1)\r
22d1f978
RN
303 ],\r
304 NULL\r
305 );\r
306 HiiCreateSubTitleOpCode (StartOpCodeHandle, Token, 0, 0, 1);\r
307 NeedEndOp = TRUE;\r
308 }\r
309\r
5caec787 310 ASSERT (Option->Description != NULL);\r
0a6f4824 311\r
cb7d01c0 312 Token = HiiSetString (HiiHandle, 0, Option->Description, NULL);\r
5c08e117 313\r
314 TempStr = DevicePathToStr (Option->DevicePath);\r
44cbebec 315 HelpSize = StrSize (TempStr) + StrSize (L"Device Path : ");\r
577870d5 316 HelpString = AllocateZeroPool (HelpSize);\r
5c08e117 317 ASSERT (HelpString != NULL);\r
577870d5 318 StrCatS (HelpString, HelpSize / sizeof (CHAR16), L"Device Path : ");\r
44cbebec 319 StrCatS (HelpString, HelpSize / sizeof (CHAR16), TempStr);\r
5c08e117 320\r
cb7d01c0 321 HelpToken = HiiSetString (HiiHandle, 0, HelpString, NULL);\r
5c08e117 322\r
75bf9d0e
LG
323 HiiCreateActionOpCode (\r
324 StartOpCodeHandle,\r
5c08e117 325 mKeyInput,\r
326 Token,\r
327 HelpToken,\r
328 EFI_IFR_FLAG_CALLBACK,\r
75bf9d0e 329 0\r
5c08e117 330 );\r
331 }\r
332\r
22d1f978
RN
333 if (NeedEndOp) {\r
334 HiiCreateEndOpCode (StartOpCodeHandle);\r
335 }\r
336\r
75bf9d0e 337 HiiUpdateForm (\r
5c08e117 338 HiiHandle,\r
e24fc103 339 &gBootManagerFormSetGuid,\r
5c08e117 340 BOOT_MANAGER_FORM_ID,\r
75bf9d0e
LG
341 StartOpCodeHandle,\r
342 EndOpCodeHandle\r
5c08e117 343 );\r
75bf9d0e
LG
344\r
345 HiiFreeOpCodeHandle (StartOpCodeHandle);\r
346 HiiFreeOpCodeHandle (EndOpCodeHandle);\r
5c08e117 347\r
348 ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
349 Status = gFormBrowser2->SendForm (\r
350 gFormBrowser2,\r
351 &HiiHandle,\r
352 1,\r
e24fc103 353 &gBootManagerFormSetGuid,\r
5c08e117 354 0,\r
355 NULL,\r
356 &ActionRequest\r
357 );\r
358 if (ActionRequest == EFI_BROWSER_ACTION_REQUEST_RESET) {\r
359 EnableResetRequired ();\r
360 }\r
361\r
362 if (gOption == NULL) {\r
363 return ;\r
364 }\r
365\r
366 //\r
baf46e70 367 // Will leave browser, check any reset required change is applied? if yes, reset system\r
5c08e117 368 //\r
369 SetupResetReminder ();\r
370\r
2df686c6 371 //\r
372 // Restore to original mode before launching boot option.\r
373 //\r
374 BdsSetConsoleMode (FALSE);\r
375\r
5c08e117 376 //\r
377 // parse the selected option\r
378 //\r
379 Status = BdsLibBootViaBootOption (gOption, gOption->DevicePath, &ExitDataSize, &ExitData);\r
380\r
381 if (!EFI_ERROR (Status)) {\r
382 gOption->StatusString = GetStringById (STRING_TOKEN (STR_BOOT_SUCCEEDED));\r
383 PlatformBdsBootSuccess (gOption);\r
384 } else {\r
385 gOption->StatusString = GetStringById (STRING_TOKEN (STR_BOOT_FAILED));\r
386 PlatformBdsBootFail (gOption, Status, ExitData, ExitDataSize);\r
387 gST->ConOut->OutputString (\r
388 gST->ConOut,\r
389 GetStringById (STRING_TOKEN (STR_ANY_KEY_CONTINUE))\r
390 );\r
391 gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);\r
392 }\r
393}\r