]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - IntelFrameworkModulePkg/Universal/BdsDxe/BootMngr/BootManager.c
Update for IntelFrameworkModulePkg.
[mirror_edk2.git] / IntelFrameworkModulePkg / Universal / BdsDxe / BootMngr / BootManager.c
... / ...
CommitLineData
1/** @file\r
2 The platform boot manager reference implementation\r
3\r
4Copyright (c) 2004 - 2011, Intel Corporation. All rights reserved.<BR>\r
5This program and the accompanying materials\r
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
18LIST_ENTRY mBootOptionsList;\r
19BDS_COMMON_OPTION *gOption;\r
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
31\r
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
42 BOOT_MANAGER_FORMSET_GUID\r
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
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
66 This call back function is registered with Boot Manager formset.\r
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
98 if (Action == EFI_BROWSER_ACTION_CHANGED) {\r
99 if ((Value == NULL) || (ActionRequest == NULL)) {\r
100 return EFI_INVALID_PARAMETER;\r
101 }\r
102\r
103 //\r
104 // Initialize the key count\r
105 //\r
106 KeyCount = 0;\r
107\r
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
110\r
111 KeyCount++;\r
112\r
113 gOption = Option;\r
114\r
115 //\r
116 // Is this device the one chosen?\r
117 //\r
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
130 }\r
131\r
132 return EFI_SUCCESS;\r
133 }\r
134\r
135 //\r
136 // All other action return unsupported.\r
137 //\r
138 return EFI_UNSUPPORTED;\r
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
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
148\r
149**/\r
150EFI_STATUS\r
151InitializeBootManager (\r
152 VOID\r
153 )\r
154{\r
155 EFI_STATUS Status;\r
156\r
157 //\r
158 // Install Device Path Protocol and Config Access protocol to driver handle\r
159 //\r
160 Status = gBS->InstallMultipleProtocolInterfaces (\r
161 &gBootManagerPrivate.DriverHandle,\r
162 &gEfiDevicePathProtocolGuid,\r
163 &mBootManagerHiiVendorDevicePath,\r
164 &gEfiHiiConfigAccessProtocolGuid,\r
165 &gBootManagerPrivate.ConfigAccess,\r
166 NULL\r
167 );\r
168 ASSERT_EFI_ERROR (Status);\r
169\r
170 //\r
171 // Publish our HII data\r
172 //\r
173 gBootManagerPrivate.HiiHandle = HiiAddPackages (\r
174 &gBootManagerFormSetGuid,\r
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
185 return Status;\r
186}\r
187\r
188/**\r
189 This function invokes Boot Manager. If all devices have not a chance to be connected,\r
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
203 CHAR16 *ExitData;\r
204 UINTN ExitDataSize;\r
205 EFI_STRING_ID Token;\r
206 EFI_INPUT_KEY Key;\r
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
213 VOID *StartOpCodeHandle;\r
214 VOID *EndOpCodeHandle;\r
215 EFI_IFR_GUID_LABEL *StartLabel;\r
216 EFI_IFR_GUID_LABEL *EndLabel;\r
217 UINT16 DeviceType;\r
218 BOOLEAN IsLegacyOption;\r
219 BOOLEAN NeedEndOp;\r
220\r
221 DeviceType = (UINT16) -1;\r
222 gOption = NULL;\r
223 InitializeListHead (&mBootOptionsList);\r
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
232\r
233 BdsLibEnumerateAllBootOption (&mBootOptionsList);\r
234\r
235 HiiHandle = gBootManagerPrivate.HiiHandle;\r
236\r
237 //\r
238 // Allocate space for creation of UpdateData Buffer\r
239 //\r
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
259\r
260 mKeyInput = 0;\r
261 NeedEndOp = FALSE;\r
262 for (Link = GetFirstNode (&mBootOptionsList); !IsNull (&mBootOptionsList, Link); Link = GetNextNode (&mBootOptionsList, Link)) {\r
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
273 if ((Option->Attribute & LOAD_OPTION_HIDDEN) != 0) {\r
274 continue;\r
275 }\r
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
308 ASSERT (Option->Description != NULL);\r
309 \r
310 Token = HiiSetString (HiiHandle, 0, Option->Description, NULL);\r
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
319 HelpToken = HiiSetString (HiiHandle, 0, HelpString, NULL);\r
320\r
321 HiiCreateActionOpCode (\r
322 StartOpCodeHandle,\r
323 mKeyInput,\r
324 Token,\r
325 HelpToken,\r
326 EFI_IFR_FLAG_CALLBACK,\r
327 0\r
328 );\r
329 }\r
330\r
331 if (NeedEndOp) {\r
332 HiiCreateEndOpCode (StartOpCodeHandle);\r
333 }\r
334\r
335 HiiUpdateForm (\r
336 HiiHandle,\r
337 &gBootManagerFormSetGuid,\r
338 BOOT_MANAGER_FORM_ID,\r
339 StartOpCodeHandle,\r
340 EndOpCodeHandle\r
341 );\r
342\r
343 HiiFreeOpCodeHandle (StartOpCodeHandle);\r
344 HiiFreeOpCodeHandle (EndOpCodeHandle);\r
345\r
346 ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
347 Status = gFormBrowser2->SendForm (\r
348 gFormBrowser2,\r
349 &HiiHandle,\r
350 1,\r
351 &gBootManagerFormSetGuid,\r
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
365 // Will leave browser, check any reset required change is applied? if yes, reset system\r
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