]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Application/UiApp/BootMngr/BootManager.c
MdeModulePkg:Use safe string functions in UiApp.
[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
222 UINTN Index;\r
223 EFI_BOOT_MANAGER_LOAD_OPTION *BootOption;\r
224 UINTN BootOptionCount;\r
225 EFI_STRING_ID Token;\r
226 CHAR16 *HelpString;\r
227 EFI_STRING_ID HelpToken;\r
228 UINT16 *TempStr;\r
229 EFI_HII_HANDLE HiiHandle;\r
230 UINTN TempSize;\r
231 VOID *StartOpCodeHandle;\r
232 VOID *EndOpCodeHandle;\r
233 EFI_IFR_GUID_LABEL *StartLabel;\r
234 EFI_IFR_GUID_LABEL *EndLabel;\r
235 UINT16 DeviceType;\r
236 BOOLEAN IsLegacyOption;\r
237 BOOLEAN NeedEndOp;\r
238 UINT16 KeyInput;\r
d91cb870 239 UINTN DestMax;\r
143f0b1d
ED
240\r
241 DeviceType = (UINT16) -1;\r
242\r
243 //\r
244 // for better user experience\r
245 // 1. User changes HD configuration (e.g.: unplug HDD), here we have a chance to remove the HDD boot option\r
246 // 2. User enables/disables UEFI PXE, here we have a chance to add/remove EFI Network boot option\r
247 //\r
248 EfiBootManagerRefreshAllBootOption ();\r
249\r
250 BootOption = EfiBootManagerGetLoadOptions (&BootOptionCount, LoadOptionTypeBoot);\r
251\r
252 HiiHandle = gBootManagerPrivate.HiiHandle;\r
253\r
254 //\r
255 // Allocate space for creation of UpdateData Buffer\r
256 //\r
257 StartOpCodeHandle = HiiAllocateOpCodeHandle ();\r
258 ASSERT (StartOpCodeHandle != NULL);\r
259\r
260 EndOpCodeHandle = HiiAllocateOpCodeHandle ();\r
261 ASSERT (EndOpCodeHandle != NULL);\r
262\r
263 //\r
264 // Create Hii Extend Label OpCode as the start opcode\r
265 //\r
266 StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (StartOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));\r
267 StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;\r
268 StartLabel->Number = LABEL_BOOT_OPTION;\r
269\r
270 //\r
271 // Create Hii Extend Label OpCode as the end opcode\r
272 //\r
273 EndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (EndOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));\r
274 EndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;\r
275 EndLabel->Number = LABEL_BOOT_OPTION_END;\r
276\r
277 KeyInput = 0;\r
278 NeedEndOp = FALSE;\r
279 for (Index = 0; Index < BootOptionCount; Index++) {\r
280 //\r
281 // At this stage we are creating a menu entry, thus the Keys are reproduceable\r
282 //\r
283 KeyInput++;\r
284\r
285 //\r
286 // Don't display the hidden/inactive boot option\r
287 //\r
288 if (((BootOption[Index].Attributes & LOAD_OPTION_HIDDEN) != 0) || ((BootOption[Index].Attributes & LOAD_OPTION_ACTIVE) == 0)) {\r
289 continue;\r
290 }\r
291\r
292 //\r
293 // Group the legacy boot option in the sub title created dynamically\r
294 //\r
295 IsLegacyOption = (BOOLEAN) (\r
296 (DevicePathType (BootOption[Index].FilePath) == BBS_DEVICE_PATH) &&\r
297 (DevicePathSubType (BootOption[Index].FilePath) == BBS_BBS_DP)\r
298 );\r
299\r
300 if (!IsLegacyOption && NeedEndOp) {\r
301 NeedEndOp = FALSE;\r
302 HiiCreateEndOpCode (StartOpCodeHandle);\r
303 }\r
304 \r
305 if (IsLegacyOption && DeviceType != ((BBS_BBS_DEVICE_PATH *) BootOption[Index].FilePath)->DeviceType) {\r
306 if (NeedEndOp) {\r
307 HiiCreateEndOpCode (StartOpCodeHandle);\r
308 }\r
309\r
310 DeviceType = ((BBS_BBS_DEVICE_PATH *) BootOption[Index].FilePath)->DeviceType;\r
311 Token = HiiSetString (\r
312 HiiHandle,\r
313 0,\r
314 mDeviceTypeStr[\r
315 MIN (DeviceType & 0xF, sizeof (mDeviceTypeStr) / sizeof (mDeviceTypeStr[0]) - 1)\r
316 ],\r
317 NULL\r
318 );\r
319 HiiCreateSubTitleOpCode (StartOpCodeHandle, Token, 0, 0, 1);\r
320 NeedEndOp = TRUE;\r
321 }\r
322\r
323 ASSERT (BootOption[Index].Description != NULL);\r
324 \r
325 Token = HiiSetString (HiiHandle, 0, BootOption[Index].Description, NULL);\r
326\r
327 TempStr = UiDevicePathToStr (BootOption[Index].FilePath);\r
328 TempSize = StrSize (TempStr);\r
d91cb870 329 DestMax = (TempSize + StrSize (L"Device Path : ")) / sizeof(CHAR16);\r
143f0b1d
ED
330 HelpString = AllocateZeroPool (TempSize + StrSize (L"Device Path : "));\r
331 ASSERT (HelpString != NULL);\r
d91cb870
DB
332 StrCatS (HelpString, DestMax, L"Device Path : ");\r
333 StrCatS (HelpString, DestMax, TempStr);\r
143f0b1d
ED
334\r
335 HelpToken = HiiSetString (HiiHandle, 0, HelpString, NULL);\r
336\r
337 HiiCreateActionOpCode (\r
338 StartOpCodeHandle,\r
339 KeyInput,\r
340 Token,\r
341 HelpToken,\r
342 EFI_IFR_FLAG_CALLBACK,\r
343 0\r
344 );\r
345 }\r
346\r
347 if (NeedEndOp) {\r
348 HiiCreateEndOpCode (StartOpCodeHandle);\r
349 }\r
350\r
351 HiiUpdateForm (\r
352 HiiHandle,\r
353 &mBootManagerGuid,\r
354 BOOT_MANAGER_FORM_ID,\r
355 StartOpCodeHandle,\r
356 EndOpCodeHandle\r
357 );\r
358\r
359 HiiFreeOpCodeHandle (StartOpCodeHandle);\r
360 HiiFreeOpCodeHandle (EndOpCodeHandle);\r
361 \r
362 EfiBootManagerFreeLoadOptions (BootOption, BootOptionCount);\r
363}\r
364\r
365\r
366/**\r
367 Remove the installed packages from the HII Database. \r
368\r
369**/\r
370VOID\r
371FreeBootManager (\r
372 VOID\r
373 )\r
374{\r
375 EFI_STATUS Status;\r
376 Status = gBS->UninstallMultipleProtocolInterfaces (\r
377 gBootManagerPrivate.DriverHandle,\r
378 &gEfiDevicePathProtocolGuid,\r
379 &mBootManagerHiiVendorDevicePath,\r
380 &gEfiHiiConfigAccessProtocolGuid,\r
381 &gBootManagerPrivate.ConfigAccess,\r
382 NULL\r
383 );\r
384 ASSERT_EFI_ERROR (Status);\r
385 \r
386 HiiRemovePackages (gBootManagerPrivate.HiiHandle);\r
387}\r