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