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