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