]> git.proxmox.com Git - mirror_edk2.git/blame - IntelFrameworkModulePkg/Universal/BdsDxe/BootMngr/BootManager.c
Driver health management implementation in BDS based on UEFI Specification 2.3.
[mirror_edk2.git] / IntelFrameworkModulePkg / Universal / BdsDxe / BootMngr / BootManager.c
CommitLineData
5c08e117 1/** @file\r
2 The platform boot manager reference implementation\r
3\r
4Copyright (c) 2004 - 2008, Intel Corporation. <BR>\r
5All rights reserved. This 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
18EFI_GUID mBootManagerGuid = BOOT_MANAGER_FORMSET_GUID;\r
19LIST_ENTRY *mBootOptionsList;\r
20BDS_COMMON_OPTION *gOption;\r
21\r
f6f910dd 22HII_VENDOR_DEVICE_PATH mBootManagerHiiVendorDevicePath = {\r
23 {\r
24 {\r
25 HARDWARE_DEVICE_PATH,\r
26 HW_VENDOR_DP,\r
27 {\r
28 (UINT8) (sizeof (VENDOR_DEVICE_PATH)),\r
29 (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8)\r
30 }\r
31 },\r
32 //\r
33 // {1DDDBE15-481D-4d2b-8277-B191EAF66525}\r
34 //\r
35 { 0x1dddbe15, 0x481d, 0x4d2b, { 0x82, 0x77, 0xb1, 0x91, 0xea, 0xf6, 0x65, 0x25 } }\r
36 },\r
37 {\r
38 END_DEVICE_PATH_TYPE,\r
39 END_ENTIRE_DEVICE_PATH_SUBTYPE,\r
40 { \r
41 (UINT8) (END_DEVICE_PATH_LENGTH),\r
42 (UINT8) ((END_DEVICE_PATH_LENGTH) >> 8)\r
43 }\r
44 }\r
45};\r
46\r
5c08e117 47BOOT_MANAGER_CALLBACK_DATA gBootManagerPrivate = {\r
48 BOOT_MANAGER_CALLBACK_DATA_SIGNATURE,\r
49 NULL,\r
50 NULL,\r
51 {\r
52 FakeExtractConfig,\r
53 FakeRouteConfig,\r
54 BootManagerCallback\r
55 }\r
56};\r
57\r
58/**\r
59 This call back funtion is registered with Boot Manager formset.\r
60 When user selects a boot option, this call back function will\r
61 be triggered. The boot option is saved for later processing.\r
62\r
63\r
64 @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
65 @param Action Specifies the type of action taken by the browser.\r
66 @param QuestionId A unique value which is sent to the original exporting driver\r
67 so that it can identify the type of data to expect.\r
68 @param Type The type of value for the question.\r
69 @param Value A pointer to the data being sent to the original exporting driver.\r
70 @param ActionRequest On return, points to the action requested by the callback function.\r
71\r
72 @retval EFI_SUCCESS The callback successfully handled the action.\r
73 @retval EFI_INVALID_PARAMETER The setup browser call this function with invalid parameters.\r
74\r
75**/\r
76EFI_STATUS\r
77EFIAPI\r
78BootManagerCallback (\r
79 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,\r
80 IN EFI_BROWSER_ACTION Action,\r
81 IN EFI_QUESTION_ID QuestionId,\r
82 IN UINT8 Type,\r
83 IN EFI_IFR_TYPE_VALUE *Value,\r
84 OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest\r
85 )\r
86{\r
87 BDS_COMMON_OPTION *Option;\r
88 LIST_ENTRY *Link;\r
89 UINT16 KeyCount;\r
90\r
91 if ((Value == NULL) || (ActionRequest == NULL)) {\r
92 return EFI_INVALID_PARAMETER;\r
93 }\r
94\r
95 //\r
96 // Initialize the key count\r
97 //\r
98 KeyCount = 0;\r
99\r
100 for (Link = mBootOptionsList->ForwardLink; Link != mBootOptionsList; Link = Link->ForwardLink) {\r
101 Option = CR (Link, BDS_COMMON_OPTION, Link, BDS_LOAD_OPTION_SIGNATURE);\r
102\r
103 KeyCount++;\r
104\r
105 gOption = Option;\r
106\r
107 //\r
108 // Is this device the one chosen?\r
109 //\r
110 if (KeyCount == QuestionId) {\r
111 //\r
112 // Assigning the returned Key to a global allows the original routine to know what was chosen\r
113 //\r
114 mKeyInput = QuestionId;\r
115\r
116 //\r
117 // Request to exit SendForm(), so that we could boot the selected option\r
118 //\r
119 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT;\r
120 break;\r
121 }\r
122 }\r
123\r
124 return EFI_SUCCESS;\r
125}\r
126\r
127/**\r
128\r
129 Registers HII packages for the Boot Manger to HII Database.\r
130 It also registers the browser call back function.\r
131\r
cb7d01c0 132 @retval EFI_SUCCESS HII packages for the Boot Manager were registered successfully.\r
133 @retval EFI_OUT_OF_RESOURCES HII packages for the Boot Manager failed to be registered.\r
5c08e117 134\r
135**/\r
136EFI_STATUS\r
137InitializeBootManager (\r
138 VOID\r
139 )\r
140{\r
141 EFI_STATUS Status;\r
5c08e117 142\r
143 //\r
f6f910dd 144 // Install Device Path Protocol and Config Access protocol to driver handle\r
5c08e117 145 //\r
f6f910dd 146 Status = gBS->InstallMultipleProtocolInterfaces (\r
5c08e117 147 &gBootManagerPrivate.DriverHandle,\r
f6f910dd 148 &gEfiDevicePathProtocolGuid,\r
149 &mBootManagerHiiVendorDevicePath,\r
5c08e117 150 &gEfiHiiConfigAccessProtocolGuid,\r
f6f910dd 151 &gBootManagerPrivate.ConfigAccess,\r
152 NULL\r
5c08e117 153 );\r
154 ASSERT_EFI_ERROR (Status);\r
155\r
156 //\r
157 // Publish our HII data\r
158 //\r
cb7d01c0 159 gBootManagerPrivate.HiiHandle = HiiAddPackages (\r
160 &mBootManagerGuid,\r
161 gBootManagerPrivate.DriverHandle,\r
162 BootManagerVfrBin,\r
163 BdsDxeStrings,\r
164 NULL\r
165 );\r
166 if (gBootManagerPrivate.HiiHandle == NULL) {\r
167 Status = EFI_OUT_OF_RESOURCES;\r
168 } else {\r
169 Status = EFI_SUCCESS;\r
170 }\r
5c08e117 171 return Status;\r
172}\r
173\r
174/**\r
175 This funtion invokees Boot Manager. If all devices have not a chance to be connected,\r
176 the connect all will be triggered. It then enumerate all boot options. If \r
177 a boot option from the Boot Manager page is selected, Boot Manager will boot\r
178 from this boot option.\r
179 \r
180**/\r
181VOID\r
182CallBootManager (\r
183 VOID\r
184 )\r
185{\r
186 EFI_STATUS Status;\r
187 BDS_COMMON_OPTION *Option;\r
188 LIST_ENTRY *Link;\r
5c08e117 189 CHAR16 *ExitData;\r
190 UINTN ExitDataSize;\r
191 EFI_STRING_ID Token;\r
192 EFI_INPUT_KEY Key;\r
193 LIST_ENTRY BdsBootOptionList;\r
194 CHAR16 *HelpString;\r
195 EFI_STRING_ID HelpToken;\r
196 UINT16 *TempStr;\r
197 EFI_HII_HANDLE HiiHandle;\r
198 EFI_BROWSER_ACTION_REQUEST ActionRequest;\r
199 UINTN TempSize;\r
75bf9d0e
LG
200 VOID *StartOpCodeHandle;\r
201 VOID *EndOpCodeHandle;\r
202 EFI_IFR_GUID_LABEL *StartLabel;\r
203 EFI_IFR_GUID_LABEL *EndLabel;\r
5caec787 204 CHAR16 *HiiString;\r
8d3b5aff 205 CHAR16 *BootStringNumber;\r
429cac9c 206 UINTN DevicePathType;\r
7edfacbf 207 UINTN BufferSize;\r
5c08e117 208\r
209 gOption = NULL;\r
210 InitializeListHead (&BdsBootOptionList);\r
211\r
212 //\r
213 // Connect all prior to entering the platform setup menu.\r
214 //\r
215 if (!gConnectAllHappened) {\r
216 BdsLibConnectAllDriversToAllControllers ();\r
217 gConnectAllHappened = TRUE;\r
218 }\r
219 //\r
220 // BugBug: Here we can not remove the legacy refresh macro, so we need\r
221 // get the boot order every time from "BootOrder" variable.\r
222 // Recreate the boot option list base on the BootOrder variable\r
223 //\r
224 BdsLibEnumerateAllBootOption (&BdsBootOptionList);\r
225\r
226 mBootOptionsList = &BdsBootOptionList;\r
227\r
228 HiiHandle = gBootManagerPrivate.HiiHandle;\r
229\r
230 //\r
231 // Allocate space for creation of UpdateData Buffer\r
232 //\r
75bf9d0e
LG
233 StartOpCodeHandle = HiiAllocateOpCodeHandle ();\r
234 ASSERT (StartOpCodeHandle != NULL);\r
235\r
236 EndOpCodeHandle = HiiAllocateOpCodeHandle ();\r
237 ASSERT (EndOpCodeHandle != NULL);\r
238\r
239 //\r
240 // Create Hii Extend Label OpCode as the start opcode\r
241 //\r
242 StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (StartOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));\r
243 StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;\r
244 StartLabel->Number = LABEL_BOOT_OPTION;\r
245\r
246 //\r
247 // Create Hii Extend Label OpCode as the end opcode\r
248 //\r
249 EndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (EndOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));\r
250 EndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;\r
251 EndLabel->Number = LABEL_BOOT_OPTION_END;\r
5c08e117 252\r
253 mKeyInput = 0;\r
254\r
255 for (Link = BdsBootOptionList.ForwardLink; Link != &BdsBootOptionList; Link = Link->ForwardLink) {\r
256 Option = CR (Link, BDS_COMMON_OPTION, Link, BDS_LOAD_OPTION_SIGNATURE);\r
257\r
258 //\r
259 // At this stage we are creating a menu entry, thus the Keys are reproduceable\r
260 //\r
261 mKeyInput++;\r
262\r
263 //\r
264 // Don't display the boot option marked as LOAD_OPTION_HIDDEN\r
265 //\r
7ec9caab 266 if ((Option->Attribute & LOAD_OPTION_HIDDEN) != 0) {\r
5c08e117 267 continue;\r
268 }\r
8d3b5aff 269 \r
270 //\r
271 // Replace description string with UNI file string.\r
272 //\r
429cac9c 273 BootStringNumber = NULL;\r
8d3b5aff 274 \r
429cac9c 275 DevicePathType = BdsGetBootTypeFromDevicePath (Option->DevicePath);\r
5caec787 276\r
429cac9c 277 //\r
278 // store number string of boot option temporary.\r
279 //\r
5caec787 280 HiiString = NULL;\r
429cac9c 281 switch (DevicePathType) {\r
282 case BDS_EFI_ACPI_FLOPPY_BOOT:\r
5caec787 283 HiiString = GetStringById (STRING_TOKEN (STR_DESCRIPTION_FLOPPY));\r
429cac9c 284 break;\r
285 case BDS_EFI_MEDIA_CDROM_BOOT:\r
5caec787 286 case BDS_EFI_MESSAGE_SATA_BOOT:\r
287 case BDS_EFI_MESSAGE_ATAPI_BOOT:\r
288 HiiString = GetStringById (STRING_TOKEN (STR_DESCRIPTION_DVD));\r
429cac9c 289 break;\r
290 case BDS_EFI_MESSAGE_USB_DEVICE_BOOT:\r
5caec787 291 HiiString = GetStringById (STRING_TOKEN (STR_DESCRIPTION_USB));\r
429cac9c 292 break;\r
293 case BDS_EFI_MESSAGE_SCSI_BOOT:\r
5caec787 294 HiiString = GetStringById (STRING_TOKEN (STR_DESCRIPTION_SCSI));\r
429cac9c 295 break;\r
296 case BDS_EFI_MESSAGE_MISC_BOOT:\r
5caec787 297 HiiString = GetStringById (STRING_TOKEN (STR_DESCRIPTION_MISC));\r
429cac9c 298 break;\r
299 case BDS_EFI_MESSAGE_MAC_BOOT:\r
5caec787 300 HiiString = GetStringById (STRING_TOKEN (STR_DESCRIPTION_NETWORK));\r
429cac9c 301 break;\r
5caec787 302 case BBS_DEVICE_PATH:\r
303 //\r
304 // Do nothing for legacy boot option.\r
305 //\r
306 break;\r
307 default:\r
308 DEBUG((EFI_D_INFO, "Can not find HiiString for given device path type 0x%x\n", DevicePathType));\r
8d3b5aff 309 }\r
5caec787 310\r
311 //\r
312 // If found Hii description string then cat Hii string with original description.\r
313 //\r
314 if (HiiString != NULL) {\r
315 BootStringNumber = Option->Description;\r
7edfacbf 316 BufferSize = StrSize(BootStringNumber);\r
317 BufferSize += StrSize(HiiString);\r
318 Option->Description = AllocateZeroPool(BufferSize);\r
5caec787 319 StrCpy (Option->Description, HiiString);\r
429cac9c 320 if (StrnCmp (BootStringNumber, L"0", 1) != 0) {\r
321 StrCat (Option->Description, L" ");\r
322 StrCat (Option->Description, BootStringNumber);\r
5caec787 323 } \r
429cac9c 324 \r
5caec787 325 FreePool (HiiString);\r
429cac9c 326 FreePool (BootStringNumber);\r
8d3b5aff 327 }\r
429cac9c 328 \r
5caec787 329 ASSERT (Option->Description != NULL);\r
330 \r
cb7d01c0 331 Token = HiiSetString (HiiHandle, 0, Option->Description, NULL);\r
5c08e117 332\r
333 TempStr = DevicePathToStr (Option->DevicePath);\r
334 TempSize = StrSize (TempStr);\r
335 HelpString = AllocateZeroPool (TempSize + StrSize (L"Device Path : "));\r
336 ASSERT (HelpString != NULL);\r
337 StrCat (HelpString, L"Device Path : ");\r
338 StrCat (HelpString, TempStr);\r
339\r
cb7d01c0 340 HelpToken = HiiSetString (HiiHandle, 0, HelpString, NULL);\r
5c08e117 341\r
75bf9d0e
LG
342 HiiCreateActionOpCode (\r
343 StartOpCodeHandle,\r
5c08e117 344 mKeyInput,\r
345 Token,\r
346 HelpToken,\r
347 EFI_IFR_FLAG_CALLBACK,\r
75bf9d0e 348 0\r
5c08e117 349 );\r
350 }\r
351\r
75bf9d0e 352 HiiUpdateForm (\r
5c08e117 353 HiiHandle,\r
354 &mBootManagerGuid,\r
355 BOOT_MANAGER_FORM_ID,\r
75bf9d0e
LG
356 StartOpCodeHandle,\r
357 EndOpCodeHandle\r
5c08e117 358 );\r
75bf9d0e
LG
359\r
360 HiiFreeOpCodeHandle (StartOpCodeHandle);\r
361 HiiFreeOpCodeHandle (EndOpCodeHandle);\r
5c08e117 362\r
363 ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
364 Status = gFormBrowser2->SendForm (\r
365 gFormBrowser2,\r
366 &HiiHandle,\r
367 1,\r
75bf9d0e 368 &mBootManagerGuid,\r
5c08e117 369 0,\r
370 NULL,\r
371 &ActionRequest\r
372 );\r
373 if (ActionRequest == EFI_BROWSER_ACTION_REQUEST_RESET) {\r
374 EnableResetRequired ();\r
375 }\r
376\r
377 if (gOption == NULL) {\r
378 return ;\r
379 }\r
380\r
381 //\r
382 //Will leave browser, check any reset required change is applied? if yes, reset system\r
383 //\r
384 SetupResetReminder ();\r
385\r
386 //\r
387 // parse the selected option\r
388 //\r
389 Status = BdsLibBootViaBootOption (gOption, gOption->DevicePath, &ExitDataSize, &ExitData);\r
390\r
391 if (!EFI_ERROR (Status)) {\r
392 gOption->StatusString = GetStringById (STRING_TOKEN (STR_BOOT_SUCCEEDED));\r
393 PlatformBdsBootSuccess (gOption);\r
394 } else {\r
395 gOption->StatusString = GetStringById (STRING_TOKEN (STR_BOOT_FAILED));\r
396 PlatformBdsBootFail (gOption, Status, ExitData, ExitDataSize);\r
397 gST->ConOut->OutputString (\r
398 gST->ConOut,\r
399 GetStringById (STRING_TOKEN (STR_ANY_KEY_CONTINUE))\r
400 );\r
401 gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);\r
402 }\r
403}\r