]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Application/UiApp/BootMngr/BootManager.c
MdeModulePkg: Update UiApp to not display itself
[mirror_edk2.git] / MdeModulePkg / Application / UiApp / BootMngr / BootManager.c
CommitLineData
143f0b1d
ED
1/** @file\r
2 The platform boot manager reference implementation\r
3\r
afc244a5 4Copyright (c) 2004 - 2015, Intel Corporation. All rights reserved.<BR>\r
143f0b1d
ED
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
17EFI_GUID mBootManagerGuid = BOOT_MANAGER_FORMSET_GUID;\r
18CHAR16 *mDeviceTypeStr[] = {\r
19 L"Legacy BEV",\r
20 L"Legacy Floppy",\r
21 L"Legacy Hard Drive",\r
22 L"Legacy CD ROM",\r
23 L"Legacy PCMCIA",\r
24 L"Legacy USB",\r
25 L"Legacy Embedded Network",\r
26 L"Legacy Unknown Device"\r
27};\r
28\r
29\r
30HII_VENDOR_DEVICE_PATH mBootManagerHiiVendorDevicePath = {\r
31 {\r
32 {\r
33 HARDWARE_DEVICE_PATH,\r
34 HW_VENDOR_DP,\r
35 {\r
36 (UINT8) (sizeof (VENDOR_DEVICE_PATH)),\r
37 (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8)\r
38 }\r
39 },\r
40 //\r
41 // {1DDDBE15-481D-4d2b-8277-B191EAF66525}\r
42 //\r
43 { 0x1dddbe15, 0x481d, 0x4d2b, { 0x82, 0x77, 0xb1, 0x91, 0xea, 0xf6, 0x65, 0x25 } }\r
44 },\r
45 {\r
46 END_DEVICE_PATH_TYPE,\r
47 END_ENTIRE_DEVICE_PATH_SUBTYPE,\r
48 { \r
49 (UINT8) (END_DEVICE_PATH_LENGTH),\r
50 (UINT8) ((END_DEVICE_PATH_LENGTH) >> 8)\r
51 }\r
52 }\r
53};\r
54\r
55BOOT_MANAGER_CALLBACK_DATA gBootManagerPrivate = {\r
56 BOOT_MANAGER_CALLBACK_DATA_SIGNATURE,\r
57 NULL,\r
58 NULL,\r
59 {\r
60 FakeExtractConfig,\r
61 FakeRouteConfig,\r
62 BootManagerCallback\r
63 }\r
64};\r
65\r
66/**\r
67 This call back function is registered with Boot Manager formset.\r
68 When user selects a boot option, this call back function will\r
69 be triggered. The boot option is saved for later processing.\r
70\r
71\r
72 @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
73 @param Action Specifies the type of action taken by the browser.\r
74 @param QuestionId A unique value which is sent to the original exporting driver\r
75 so that it can identify the type of data to expect.\r
76 @param Type The type of value for the question.\r
77 @param Value A pointer to the data being sent to the original exporting driver.\r
78 @param ActionRequest On return, points to the action requested by the callback function.\r
79\r
80 @retval EFI_SUCCESS The callback successfully handled the action.\r
81 @retval EFI_INVALID_PARAMETER The setup browser call this function with invalid parameters.\r
82\r
83**/\r
84EFI_STATUS\r
85EFIAPI\r
86BootManagerCallback (\r
87 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,\r
88 IN EFI_BROWSER_ACTION Action,\r
89 IN EFI_QUESTION_ID QuestionId,\r
90 IN UINT8 Type,\r
91 IN EFI_IFR_TYPE_VALUE *Value,\r
92 OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest\r
93 )\r
94{\r
95 UINTN Index;\r
96 EFI_BOOT_MANAGER_LOAD_OPTION *BootOption;\r
97 UINTN BootOptionCount;\r
98 UINT16 KeyCount;\r
99 EFI_INPUT_KEY Key;\r
100 EFI_BOOT_MANAGER_LOAD_OPTION Option;\r
101\r
102 if (Action != EFI_BROWSER_ACTION_CHANGED) {\r
103 //\r
104 // Do nothing for other UEFI Action. Only do call back when data is changed.\r
105 //\r
106 return EFI_UNSUPPORTED;\r
107 }\r
108\r
109 if ((Value == NULL) || (ActionRequest == NULL)) {\r
110 return EFI_INVALID_PARAMETER;\r
111 }\r
112\r
113 //\r
114 // Initialize the key count\r
115 //\r
116 KeyCount = 0;\r
117 Option.Attributes = 0;\r
118 BootOption = EfiBootManagerGetLoadOptions (&BootOptionCount, LoadOptionTypeBoot);\r
119\r
120 for (Index = 0; Index < BootOptionCount; Index++) {\r
121 KeyCount++;\r
122\r
123 EfiBootManagerInitializeLoadOption (\r
124 &Option,\r
125 BootOption[Index].OptionNumber,\r
126 BootOption[Index].OptionType,\r
127 BootOption[Index].Attributes,\r
128 BootOption[Index].Description,\r
129 BootOption[Index].FilePath,\r
130 BootOption[Index].OptionalData,\r
131 BootOption[Index].OptionalDataSize\r
132 );\r
133\r
134 //\r
135 // Is this device the one chosen?\r
136 //\r
137 if (KeyCount == QuestionId) {\r
138 //\r
139 // Clear the screen before.\r
140 //\r
141 gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));\r
142 gST->ConOut->ClearScreen (gST->ConOut);\r
143 //\r
144 // Check any reset required change is applied? if yes, reset system\r
145 //\r
146 SetupResetReminder();\r
147 //\r
148 // Parse the selected option.\r
149 //\r
150 BdsSetConsoleMode(FALSE);\r
151 EfiBootManagerBoot (&Option);\r
152 BdsSetConsoleMode(TRUE);\r
153\r
154 if (EFI_ERROR (Option.Status)) {\r
155 gST->ConOut->OutputString (\r
156 gST->ConOut,\r
157 GetStringById (STRING_TOKEN (STR_ANY_KEY_CONTINUE))\r
158 );\r
159 gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);\r
160 }\r
161 break;\r
162 }\r
163 }\r
164 EfiBootManagerFreeLoadOptions (BootOption, BootOptionCount);\r
165\r
166 return EFI_SUCCESS;\r
167}\r
168\r
169/**\r
170 Register HII packages to HII database.\r
171\r
172**/\r
173VOID\r
174InitializeBootManager (\r
175 VOID\r
176 )\r
177{\r
178 EFI_STATUS Status;\r
179\r
180 if (!gConnectAllHappened){\r
181 EfiBootManagerConnectAll();\r
182 gConnectAllHappened = TRUE;\r
183 }\r
184\r
185 //\r
186 // Install Device Path Protocol and Config Access protocol to driver handle\r
187 //\r
188 gBootManagerPrivate.DriverHandle = NULL;\r
189 Status = gBS->InstallMultipleProtocolInterfaces (\r
190 &gBootManagerPrivate.DriverHandle,\r
191 &gEfiDevicePathProtocolGuid,\r
192 &mBootManagerHiiVendorDevicePath,\r
193 &gEfiHiiConfigAccessProtocolGuid,\r
194 &gBootManagerPrivate.ConfigAccess,\r
195 NULL\r
196 );\r
197 ASSERT_EFI_ERROR (Status);\r
198\r
199 //\r
200 // Publish our HII data\r
201 //\r
202 gBootManagerPrivate.HiiHandle = HiiAddPackages (\r
203 &mBootManagerGuid,\r
204 gBootManagerPrivate.DriverHandle,\r
205 BootManagerVfrBin,\r
206 UiAppStrings,\r
207 NULL\r
208 );\r
209 ASSERT(gBootManagerPrivate.HiiHandle != NULL);\r
210}\r
211\r
212\r
213/**\r
214 Enumerate possible boot options.\r
215\r
216**/\r
217VOID\r
218EnumerateBootOptions (\r
219 VOID\r
220 )\r
221{\r
d4bf294e 222 EFI_STATUS Status;\r
143f0b1d 223 UINTN Index;\r
d4bf294e 224 EFI_DEVICE_PATH_PROTOCOL *ImageDevicePath;\r
143f0b1d
ED
225 EFI_BOOT_MANAGER_LOAD_OPTION *BootOption;\r
226 UINTN BootOptionCount;\r
227 EFI_STRING_ID Token;\r
228 CHAR16 *HelpString;\r
229 EFI_STRING_ID HelpToken;\r
230 UINT16 *TempStr;\r
231 EFI_HII_HANDLE HiiHandle;\r
232 UINTN TempSize;\r
233 VOID *StartOpCodeHandle;\r
234 VOID *EndOpCodeHandle;\r
235 EFI_IFR_GUID_LABEL *StartLabel;\r
236 EFI_IFR_GUID_LABEL *EndLabel;\r
237 UINT16 DeviceType;\r
238 BOOLEAN IsLegacyOption;\r
239 BOOLEAN NeedEndOp;\r
240 UINT16 KeyInput;\r
d91cb870 241 UINTN DestMax;\r
143f0b1d
ED
242\r
243 DeviceType = (UINT16) -1;\r
244\r
d4bf294e
RN
245 Status = gBS->HandleProtocol (gImageHandle, &gEfiLoadedImageDevicePathProtocolGuid, (VOID **) &ImageDevicePath);\r
246 ASSERT_EFI_ERROR (Status);\r
247\r
143f0b1d
ED
248 //\r
249 // for better user experience\r
250 // 1. User changes HD configuration (e.g.: unplug HDD), here we have a chance to remove the HDD boot option\r
251 // 2. User enables/disables UEFI PXE, here we have a chance to add/remove EFI Network boot option\r
252 //\r
253 EfiBootManagerRefreshAllBootOption ();\r
254\r
255 BootOption = EfiBootManagerGetLoadOptions (&BootOptionCount, LoadOptionTypeBoot);\r
256\r
257 HiiHandle = gBootManagerPrivate.HiiHandle;\r
258\r
259 //\r
260 // Allocate space for creation of UpdateData Buffer\r
261 //\r
262 StartOpCodeHandle = HiiAllocateOpCodeHandle ();\r
263 ASSERT (StartOpCodeHandle != NULL);\r
264\r
265 EndOpCodeHandle = HiiAllocateOpCodeHandle ();\r
266 ASSERT (EndOpCodeHandle != NULL);\r
267\r
268 //\r
269 // Create Hii Extend Label OpCode as the start opcode\r
270 //\r
271 StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (StartOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));\r
272 StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;\r
273 StartLabel->Number = LABEL_BOOT_OPTION;\r
274\r
275 //\r
276 // Create Hii Extend Label OpCode as the end opcode\r
277 //\r
278 EndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (EndOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));\r
279 EndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;\r
280 EndLabel->Number = LABEL_BOOT_OPTION_END;\r
281\r
282 KeyInput = 0;\r
283 NeedEndOp = FALSE;\r
284 for (Index = 0; Index < BootOptionCount; Index++) {\r
285 //\r
286 // At this stage we are creating a menu entry, thus the Keys are reproduceable\r
287 //\r
288 KeyInput++;\r
289\r
290 //\r
291 // Don't display the hidden/inactive boot option\r
292 //\r
293 if (((BootOption[Index].Attributes & LOAD_OPTION_HIDDEN) != 0) || ((BootOption[Index].Attributes & LOAD_OPTION_ACTIVE) == 0)) {\r
294 continue;\r
295 }\r
296\r
d4bf294e
RN
297 //\r
298 // Don't display myself\r
299 //\r
300 if (CompareMem (BootOption[Index].FilePath, ImageDevicePath, GetDevicePathSize (ImageDevicePath)) == 0) {\r
301 continue;\r
302 }\r
303\r
143f0b1d
ED
304 //\r
305 // Group the legacy boot option in the sub title created dynamically\r
306 //\r
307 IsLegacyOption = (BOOLEAN) (\r
308 (DevicePathType (BootOption[Index].FilePath) == BBS_DEVICE_PATH) &&\r
309 (DevicePathSubType (BootOption[Index].FilePath) == BBS_BBS_DP)\r
310 );\r
311\r
312 if (!IsLegacyOption && NeedEndOp) {\r
313 NeedEndOp = FALSE;\r
314 HiiCreateEndOpCode (StartOpCodeHandle);\r
315 }\r
316 \r
317 if (IsLegacyOption && DeviceType != ((BBS_BBS_DEVICE_PATH *) BootOption[Index].FilePath)->DeviceType) {\r
318 if (NeedEndOp) {\r
319 HiiCreateEndOpCode (StartOpCodeHandle);\r
320 }\r
321\r
322 DeviceType = ((BBS_BBS_DEVICE_PATH *) BootOption[Index].FilePath)->DeviceType;\r
323 Token = HiiSetString (\r
324 HiiHandle,\r
325 0,\r
326 mDeviceTypeStr[\r
327 MIN (DeviceType & 0xF, sizeof (mDeviceTypeStr) / sizeof (mDeviceTypeStr[0]) - 1)\r
328 ],\r
329 NULL\r
330 );\r
331 HiiCreateSubTitleOpCode (StartOpCodeHandle, Token, 0, 0, 1);\r
332 NeedEndOp = TRUE;\r
333 }\r
334\r
335 ASSERT (BootOption[Index].Description != NULL);\r
336 \r
337 Token = HiiSetString (HiiHandle, 0, BootOption[Index].Description, NULL);\r
338\r
339 TempStr = UiDevicePathToStr (BootOption[Index].FilePath);\r
340 TempSize = StrSize (TempStr);\r
d91cb870 341 DestMax = (TempSize + StrSize (L"Device Path : ")) / sizeof(CHAR16);\r
143f0b1d
ED
342 HelpString = AllocateZeroPool (TempSize + StrSize (L"Device Path : "));\r
343 ASSERT (HelpString != NULL);\r
d91cb870
DB
344 StrCatS (HelpString, DestMax, L"Device Path : ");\r
345 StrCatS (HelpString, DestMax, TempStr);\r
143f0b1d
ED
346\r
347 HelpToken = HiiSetString (HiiHandle, 0, HelpString, NULL);\r
348\r
349 HiiCreateActionOpCode (\r
350 StartOpCodeHandle,\r
351 KeyInput,\r
352 Token,\r
353 HelpToken,\r
354 EFI_IFR_FLAG_CALLBACK,\r
355 0\r
356 );\r
357 }\r
358\r
359 if (NeedEndOp) {\r
360 HiiCreateEndOpCode (StartOpCodeHandle);\r
361 }\r
362\r
363 HiiUpdateForm (\r
364 HiiHandle,\r
365 &mBootManagerGuid,\r
366 BOOT_MANAGER_FORM_ID,\r
367 StartOpCodeHandle,\r
368 EndOpCodeHandle\r
369 );\r
370\r
371 HiiFreeOpCodeHandle (StartOpCodeHandle);\r
372 HiiFreeOpCodeHandle (EndOpCodeHandle);\r
373 \r
374 EfiBootManagerFreeLoadOptions (BootOption, BootOptionCount);\r
375}\r
376\r
377\r
378/**\r
379 Remove the installed packages from the HII Database. \r
380\r
381**/\r
382VOID\r
383FreeBootManager (\r
384 VOID\r
385 )\r
386{\r
387 EFI_STATUS Status;\r
388 Status = gBS->UninstallMultipleProtocolInterfaces (\r
389 gBootManagerPrivate.DriverHandle,\r
390 &gEfiDevicePathProtocolGuid,\r
391 &mBootManagerHiiVendorDevicePath,\r
392 &gEfiHiiConfigAccessProtocolGuid,\r
393 &gBootManagerPrivate.ConfigAccess,\r
394 NULL\r
395 );\r
396 ASSERT_EFI_ERROR (Status);\r
397 \r
398 HiiRemovePackages (gBootManagerPrivate.HiiHandle);\r
399}\r