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