]> git.proxmox.com Git - mirror_edk2.git/blob - IntelFrameworkModulePkg/Universal/BdsDxe/BootMngr/BootManager.c
IntelFrameworkModulePkg: Clean up source files
[mirror_edk2.git] / IntelFrameworkModulePkg / Universal / BdsDxe / BootMngr / BootManager.c
1 /** @file
2 The platform boot manager reference implementation
3
4 Copyright (c) 2004 - 2018, 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 UINT16 mKeyInput;
18 LIST_ENTRY mBootOptionsList;
19 BDS_COMMON_OPTION *gOption;
20 CHAR16 *mDeviceTypeStr[] = {
21 L"Legacy BEV",
22 L"Legacy Floppy",
23 L"Legacy Hard Drive",
24 L"Legacy CD ROM",
25 L"Legacy PCMCIA",
26 L"Legacy USB",
27 L"Legacy Embedded Network",
28 L"Legacy Unknown Device"
29 };
30
31
32 HII_VENDOR_DEVICE_PATH mBootManagerHiiVendorDevicePath = {
33 {
34 {
35 HARDWARE_DEVICE_PATH,
36 HW_VENDOR_DP,
37 {
38 (UINT8) (sizeof (VENDOR_DEVICE_PATH)),
39 (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8)
40 }
41 },
42 BOOT_MANAGER_FORMSET_GUID
43 },
44 {
45 END_DEVICE_PATH_TYPE,
46 END_ENTIRE_DEVICE_PATH_SUBTYPE,
47 {
48 (UINT8) (END_DEVICE_PATH_LENGTH),
49 (UINT8) ((END_DEVICE_PATH_LENGTH) >> 8)
50 }
51 }
52 };
53
54 BOOT_MANAGER_CALLBACK_DATA gBootManagerPrivate = {
55 BOOT_MANAGER_CALLBACK_DATA_SIGNATURE,
56 NULL,
57 NULL,
58 {
59 FakeExtractConfig,
60 FakeRouteConfig,
61 BootManagerCallback
62 }
63 };
64
65 /**
66 This call back function is registered with Boot Manager formset.
67 When user selects a boot option, this call back function will
68 be triggered. The boot option is saved for later processing.
69
70
71 @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
72 @param Action Specifies the type of action taken by the browser.
73 @param QuestionId A unique value which is sent to the original exporting driver
74 so that it can identify the type of data to expect.
75 @param Type The type of value for the question.
76 @param Value A pointer to the data being sent to the original exporting driver.
77 @param ActionRequest On return, points to the action requested by the callback function.
78
79 @retval EFI_SUCCESS The callback successfully handled the action.
80 @retval EFI_INVALID_PARAMETER The setup browser call this function with invalid parameters.
81
82 **/
83 EFI_STATUS
84 EFIAPI
85 BootManagerCallback (
86 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
87 IN EFI_BROWSER_ACTION Action,
88 IN EFI_QUESTION_ID QuestionId,
89 IN UINT8 Type,
90 IN EFI_IFR_TYPE_VALUE *Value,
91 OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest
92 )
93 {
94 BDS_COMMON_OPTION *Option;
95 LIST_ENTRY *Link;
96 UINT16 KeyCount;
97
98 if (Action == EFI_BROWSER_ACTION_CHANGED) {
99 if ((Value == NULL) || (ActionRequest == NULL)) {
100 return EFI_INVALID_PARAMETER;
101 }
102
103 //
104 // Initialize the key count
105 //
106 KeyCount = 0;
107
108 for (Link = GetFirstNode (&mBootOptionsList); !IsNull (&mBootOptionsList, Link); Link = GetNextNode (&mBootOptionsList, Link)) {
109 Option = CR (Link, BDS_COMMON_OPTION, Link, BDS_LOAD_OPTION_SIGNATURE);
110
111 KeyCount++;
112
113 gOption = Option;
114
115 //
116 // Is this device the one chosen?
117 //
118 if (KeyCount == QuestionId) {
119 //
120 // Assigning the returned Key to a global allows the original routine to know what was chosen
121 //
122 mKeyInput = QuestionId;
123
124 //
125 // Request to exit SendForm(), so that we could boot the selected option
126 //
127 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT;
128 break;
129 }
130 }
131
132 return EFI_SUCCESS;
133 }
134
135 //
136 // All other action return unsupported.
137 //
138 return EFI_UNSUPPORTED;
139 }
140
141 /**
142
143 Registers HII packages for the Boot Manger to HII Database.
144 It also registers the browser call back function.
145
146 @retval EFI_SUCCESS HII packages for the Boot Manager were registered successfully.
147 @retval EFI_OUT_OF_RESOURCES HII packages for the Boot Manager failed to be registered.
148
149 **/
150 EFI_STATUS
151 InitializeBootManager (
152 VOID
153 )
154 {
155 EFI_STATUS Status;
156
157 //
158 // Install Device Path Protocol and Config Access protocol to driver handle
159 //
160 Status = gBS->InstallMultipleProtocolInterfaces (
161 &gBootManagerPrivate.DriverHandle,
162 &gEfiDevicePathProtocolGuid,
163 &mBootManagerHiiVendorDevicePath,
164 &gEfiHiiConfigAccessProtocolGuid,
165 &gBootManagerPrivate.ConfigAccess,
166 NULL
167 );
168 ASSERT_EFI_ERROR (Status);
169
170 //
171 // Publish our HII data
172 //
173 gBootManagerPrivate.HiiHandle = HiiAddPackages (
174 &gBootManagerFormSetGuid,
175 gBootManagerPrivate.DriverHandle,
176 BootManagerVfrBin,
177 BdsDxeStrings,
178 NULL
179 );
180 if (gBootManagerPrivate.HiiHandle == NULL) {
181 Status = EFI_OUT_OF_RESOURCES;
182 } else {
183 Status = EFI_SUCCESS;
184 }
185 return Status;
186 }
187
188 /**
189 This function invokes Boot Manager. If all devices have not a chance to be connected,
190 the connect all will be triggered. It then enumerate all boot options. If
191 a boot option from the Boot Manager page is selected, Boot Manager will boot
192 from this boot option.
193
194 **/
195 VOID
196 CallBootManager (
197 VOID
198 )
199 {
200 EFI_STATUS Status;
201 BDS_COMMON_OPTION *Option;
202 LIST_ENTRY *Link;
203 CHAR16 *ExitData;
204 UINTN ExitDataSize;
205 EFI_STRING_ID Token;
206 EFI_INPUT_KEY Key;
207 CHAR16 *HelpString;
208 UINTN HelpSize;
209 EFI_STRING_ID HelpToken;
210 UINT16 *TempStr;
211 EFI_HII_HANDLE HiiHandle;
212 EFI_BROWSER_ACTION_REQUEST ActionRequest;
213 VOID *StartOpCodeHandle;
214 VOID *EndOpCodeHandle;
215 EFI_IFR_GUID_LABEL *StartLabel;
216 EFI_IFR_GUID_LABEL *EndLabel;
217 UINT16 DeviceType;
218 BOOLEAN IsLegacyOption;
219 BOOLEAN NeedEndOp;
220
221 DeviceType = (UINT16) -1;
222 gOption = NULL;
223 InitializeListHead (&mBootOptionsList);
224
225 //
226 // Connect all prior to entering the platform setup menu.
227 //
228 if (!gConnectAllHappened) {
229 BdsLibConnectAllDriversToAllControllers ();
230 gConnectAllHappened = TRUE;
231 }
232
233 BdsLibEnumerateAllBootOption (&mBootOptionsList);
234
235 //
236 // Group the legacy boot options for the same device type
237 //
238 GroupMultipleLegacyBootOption4SameType ();
239
240 InitializeListHead (&mBootOptionsList);
241 BdsLibBuildOptionFromVar (&mBootOptionsList, L"BootOrder");
242
243 HiiHandle = gBootManagerPrivate.HiiHandle;
244
245 //
246 // Allocate space for creation of UpdateData Buffer
247 //
248 StartOpCodeHandle = HiiAllocateOpCodeHandle ();
249 ASSERT (StartOpCodeHandle != NULL);
250
251 EndOpCodeHandle = HiiAllocateOpCodeHandle ();
252 ASSERT (EndOpCodeHandle != NULL);
253
254 //
255 // Create Hii Extend Label OpCode as the start opcode
256 //
257 StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (StartOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));
258 StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
259 StartLabel->Number = LABEL_BOOT_OPTION;
260
261 //
262 // Create Hii Extend Label OpCode as the end opcode
263 //
264 EndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (EndOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));
265 EndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
266 EndLabel->Number = LABEL_BOOT_OPTION_END;
267
268 mKeyInput = 0;
269 NeedEndOp = FALSE;
270 for (Link = GetFirstNode (&mBootOptionsList); !IsNull (&mBootOptionsList, Link); Link = GetNextNode (&mBootOptionsList, Link)) {
271 Option = CR (Link, BDS_COMMON_OPTION, Link, BDS_LOAD_OPTION_SIGNATURE);
272
273 //
274 // At this stage we are creating a menu entry, thus the Keys are reproduceable
275 //
276 mKeyInput++;
277
278 //
279 // Don't display the hidden/inactive boot option
280 //
281 if (((Option->Attribute & LOAD_OPTION_HIDDEN) != 0) || ((Option->Attribute & LOAD_OPTION_ACTIVE) == 0)) {
282 continue;
283 }
284
285 //
286 // Group the legacy boot option in the sub title created dynamically
287 //
288 IsLegacyOption = (BOOLEAN) (
289 (DevicePathType (Option->DevicePath) == BBS_DEVICE_PATH) &&
290 (DevicePathSubType (Option->DevicePath) == BBS_BBS_DP)
291 );
292
293 if (!IsLegacyOption && NeedEndOp) {
294 NeedEndOp = FALSE;
295 HiiCreateEndOpCode (StartOpCodeHandle);
296 }
297
298 if (IsLegacyOption && DeviceType != ((BBS_BBS_DEVICE_PATH *) Option->DevicePath)->DeviceType) {
299 if (NeedEndOp) {
300 HiiCreateEndOpCode (StartOpCodeHandle);
301 }
302
303 DeviceType = ((BBS_BBS_DEVICE_PATH *) Option->DevicePath)->DeviceType;
304 Token = HiiSetString (
305 HiiHandle,
306 0,
307 mDeviceTypeStr[
308 MIN (DeviceType & 0xF, ARRAY_SIZE (mDeviceTypeStr) - 1)
309 ],
310 NULL
311 );
312 HiiCreateSubTitleOpCode (StartOpCodeHandle, Token, 0, 0, 1);
313 NeedEndOp = TRUE;
314 }
315
316 ASSERT (Option->Description != NULL);
317
318 Token = HiiSetString (HiiHandle, 0, Option->Description, NULL);
319
320 TempStr = DevicePathToStr (Option->DevicePath);
321 HelpSize = StrSize (TempStr) + StrSize (L"Device Path : ");
322 HelpString = AllocateZeroPool (HelpSize);
323 ASSERT (HelpString != NULL);
324 StrCatS (HelpString, HelpSize / sizeof (CHAR16), L"Device Path : ");
325 StrCatS (HelpString, HelpSize / sizeof (CHAR16), TempStr);
326
327 HelpToken = HiiSetString (HiiHandle, 0, HelpString, NULL);
328
329 HiiCreateActionOpCode (
330 StartOpCodeHandle,
331 mKeyInput,
332 Token,
333 HelpToken,
334 EFI_IFR_FLAG_CALLBACK,
335 0
336 );
337 }
338
339 if (NeedEndOp) {
340 HiiCreateEndOpCode (StartOpCodeHandle);
341 }
342
343 HiiUpdateForm (
344 HiiHandle,
345 &gBootManagerFormSetGuid,
346 BOOT_MANAGER_FORM_ID,
347 StartOpCodeHandle,
348 EndOpCodeHandle
349 );
350
351 HiiFreeOpCodeHandle (StartOpCodeHandle);
352 HiiFreeOpCodeHandle (EndOpCodeHandle);
353
354 ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;
355 Status = gFormBrowser2->SendForm (
356 gFormBrowser2,
357 &HiiHandle,
358 1,
359 &gBootManagerFormSetGuid,
360 0,
361 NULL,
362 &ActionRequest
363 );
364 if (ActionRequest == EFI_BROWSER_ACTION_REQUEST_RESET) {
365 EnableResetRequired ();
366 }
367
368 if (gOption == NULL) {
369 return ;
370 }
371
372 //
373 // Will leave browser, check any reset required change is applied? if yes, reset system
374 //
375 SetupResetReminder ();
376
377 //
378 // Restore to original mode before launching boot option.
379 //
380 BdsSetConsoleMode (FALSE);
381
382 //
383 // parse the selected option
384 //
385 Status = BdsLibBootViaBootOption (gOption, gOption->DevicePath, &ExitDataSize, &ExitData);
386
387 if (!EFI_ERROR (Status)) {
388 gOption->StatusString = GetStringById (STRING_TOKEN (STR_BOOT_SUCCEEDED));
389 PlatformBdsBootSuccess (gOption);
390 } else {
391 gOption->StatusString = GetStringById (STRING_TOKEN (STR_BOOT_FAILED));
392 PlatformBdsBootFail (gOption, Status, ExitData, ExitDataSize);
393 gST->ConOut->OutputString (
394 gST->ConOut,
395 GetStringById (STRING_TOKEN (STR_ANY_KEY_CONTINUE))
396 );
397 gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
398 }
399 }