2 The platform boot manager reference implementation
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
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.
15 #include "BootManager.h"
18 LIST_ENTRY mBootOptionsList
;
19 BDS_COMMON_OPTION
*gOption
;
20 CHAR16
*mDeviceTypeStr
[] = {
27 L
"Legacy Embedded Network",
28 L
"Legacy Unknown Device"
32 HII_VENDOR_DEVICE_PATH mBootManagerHiiVendorDevicePath
= {
38 (UINT8
) (sizeof (VENDOR_DEVICE_PATH
)),
39 (UINT8
) ((sizeof (VENDOR_DEVICE_PATH
)) >> 8)
42 BOOT_MANAGER_FORMSET_GUID
46 END_ENTIRE_DEVICE_PATH_SUBTYPE
,
48 (UINT8
) (END_DEVICE_PATH_LENGTH
),
49 (UINT8
) ((END_DEVICE_PATH_LENGTH
) >> 8)
54 BOOT_MANAGER_CALLBACK_DATA gBootManagerPrivate
= {
55 BOOT_MANAGER_CALLBACK_DATA_SIGNATURE
,
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.
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.
79 @retval EFI_SUCCESS The callback successfully handled the action.
80 @retval EFI_INVALID_PARAMETER The setup browser call this function with invalid parameters.
86 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
87 IN EFI_BROWSER_ACTION Action
,
88 IN EFI_QUESTION_ID QuestionId
,
90 IN EFI_IFR_TYPE_VALUE
*Value
,
91 OUT EFI_BROWSER_ACTION_REQUEST
*ActionRequest
94 BDS_COMMON_OPTION
*Option
;
98 if (Action
== EFI_BROWSER_ACTION_CHANGED
) {
99 if ((Value
== NULL
) || (ActionRequest
== NULL
)) {
100 return EFI_INVALID_PARAMETER
;
104 // Initialize the key count
108 for (Link
= GetFirstNode (&mBootOptionsList
); !IsNull (&mBootOptionsList
, Link
); Link
= GetNextNode (&mBootOptionsList
, Link
)) {
109 Option
= CR (Link
, BDS_COMMON_OPTION
, Link
, BDS_LOAD_OPTION_SIGNATURE
);
116 // Is this device the one chosen?
118 if (KeyCount
== QuestionId
) {
120 // Assigning the returned Key to a global allows the original routine to know what was chosen
122 mKeyInput
= QuestionId
;
125 // Request to exit SendForm(), so that we could boot the selected option
127 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_EXIT
;
136 // All other action return unsupported.
138 return EFI_UNSUPPORTED
;
143 Registers HII packages for the Boot Manger to HII Database.
144 It also registers the browser call back function.
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.
151 InitializeBootManager (
158 // Install Device Path Protocol and Config Access protocol to driver handle
160 Status
= gBS
->InstallMultipleProtocolInterfaces (
161 &gBootManagerPrivate
.DriverHandle
,
162 &gEfiDevicePathProtocolGuid
,
163 &mBootManagerHiiVendorDevicePath
,
164 &gEfiHiiConfigAccessProtocolGuid
,
165 &gBootManagerPrivate
.ConfigAccess
,
168 ASSERT_EFI_ERROR (Status
);
171 // Publish our HII data
173 gBootManagerPrivate
.HiiHandle
= HiiAddPackages (
174 &gBootManagerFormSetGuid
,
175 gBootManagerPrivate
.DriverHandle
,
180 if (gBootManagerPrivate
.HiiHandle
== NULL
) {
181 Status
= EFI_OUT_OF_RESOURCES
;
183 Status
= EFI_SUCCESS
;
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.
201 BDS_COMMON_OPTION
*Option
;
209 EFI_STRING_ID HelpToken
;
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
;
218 BOOLEAN IsLegacyOption
;
221 DeviceType
= (UINT16
) -1;
223 InitializeListHead (&mBootOptionsList
);
226 // Connect all prior to entering the platform setup menu.
228 if (!gConnectAllHappened
) {
229 BdsLibConnectAllDriversToAllControllers ();
230 gConnectAllHappened
= TRUE
;
233 BdsLibEnumerateAllBootOption (&mBootOptionsList
);
236 // Group the legacy boot options for the same device type
238 GroupMultipleLegacyBootOption4SameType ();
240 InitializeListHead (&mBootOptionsList
);
241 BdsLibBuildOptionFromVar (&mBootOptionsList
, L
"BootOrder");
243 HiiHandle
= gBootManagerPrivate
.HiiHandle
;
246 // Allocate space for creation of UpdateData Buffer
248 StartOpCodeHandle
= HiiAllocateOpCodeHandle ();
249 ASSERT (StartOpCodeHandle
!= NULL
);
251 EndOpCodeHandle
= HiiAllocateOpCodeHandle ();
252 ASSERT (EndOpCodeHandle
!= NULL
);
255 // Create Hii Extend Label OpCode as the start opcode
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
;
262 // Create Hii Extend Label OpCode as the end opcode
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
;
270 for (Link
= GetFirstNode (&mBootOptionsList
); !IsNull (&mBootOptionsList
, Link
); Link
= GetNextNode (&mBootOptionsList
, Link
)) {
271 Option
= CR (Link
, BDS_COMMON_OPTION
, Link
, BDS_LOAD_OPTION_SIGNATURE
);
274 // At this stage we are creating a menu entry, thus the Keys are reproduceable
279 // Don't display the hidden/inactive boot option
281 if (((Option
->Attribute
& LOAD_OPTION_HIDDEN
) != 0) || ((Option
->Attribute
& LOAD_OPTION_ACTIVE
) == 0)) {
286 // Group the legacy boot option in the sub title created dynamically
288 IsLegacyOption
= (BOOLEAN
) (
289 (DevicePathType (Option
->DevicePath
) == BBS_DEVICE_PATH
) &&
290 (DevicePathSubType (Option
->DevicePath
) == BBS_BBS_DP
)
293 if (!IsLegacyOption
&& NeedEndOp
) {
295 HiiCreateEndOpCode (StartOpCodeHandle
);
298 if (IsLegacyOption
&& DeviceType
!= ((BBS_BBS_DEVICE_PATH
*) Option
->DevicePath
)->DeviceType
) {
300 HiiCreateEndOpCode (StartOpCodeHandle
);
303 DeviceType
= ((BBS_BBS_DEVICE_PATH
*) Option
->DevicePath
)->DeviceType
;
304 Token
= HiiSetString (
308 MIN (DeviceType
& 0xF, ARRAY_SIZE (mDeviceTypeStr
) - 1)
312 HiiCreateSubTitleOpCode (StartOpCodeHandle
, Token
, 0, 0, 1);
316 ASSERT (Option
->Description
!= NULL
);
318 Token
= HiiSetString (HiiHandle
, 0, Option
->Description
, NULL
);
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
);
327 HelpToken
= HiiSetString (HiiHandle
, 0, HelpString
, NULL
);
329 HiiCreateActionOpCode (
334 EFI_IFR_FLAG_CALLBACK
,
340 HiiCreateEndOpCode (StartOpCodeHandle
);
345 &gBootManagerFormSetGuid
,
346 BOOT_MANAGER_FORM_ID
,
351 HiiFreeOpCodeHandle (StartOpCodeHandle
);
352 HiiFreeOpCodeHandle (EndOpCodeHandle
);
354 ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
355 Status
= gFormBrowser2
->SendForm (
359 &gBootManagerFormSetGuid
,
364 if (ActionRequest
== EFI_BROWSER_ACTION_REQUEST_RESET
) {
365 EnableResetRequired ();
368 if (gOption
== NULL
) {
373 // Will leave browser, check any reset required change is applied? if yes, reset system
375 SetupResetReminder ();
378 // Restore to original mode before launching boot option.
380 BdsSetConsoleMode (FALSE
);
383 // parse the selected option
385 Status
= BdsLibBootViaBootOption (gOption
, gOption
->DevicePath
, &ExitDataSize
, &ExitData
);
387 if (!EFI_ERROR (Status
)) {
388 gOption
->StatusString
= GetStringById (STRING_TOKEN (STR_BOOT_SUCCEEDED
));
389 PlatformBdsBootSuccess (gOption
);
391 gOption
->StatusString
= GetStringById (STRING_TOKEN (STR_BOOT_FAILED
));
392 PlatformBdsBootFail (gOption
, Status
, ExitData
, ExitDataSize
);
393 gST
->ConOut
->OutputString (
395 GetStringById (STRING_TOKEN (STR_ANY_KEY_CONTINUE
))
397 gST
->ConIn
->ReadKeyStroke (gST
->ConIn
, &Key
);