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